All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/5] DMA-BUF Heaps (destaging ION)
@ 2019-06-24 19:49 John Stultz
  2019-06-24 19:49 ` [PATCH v6 1/5] dma-buf: Add dma-buf heaps framework John Stultz
                   ` (5 more replies)
  0 siblings, 6 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Christoph Hellwig, Chenbo Feng,
	Alistair Strachan, dri-devel

Here is another pass at the dma-buf heaps patchset Andrew and I
have been working on which tries to destage a fair chunk of ION
functionality.

The patchset implements per-heap devices which can be opened
directly and then an ioctl is used to allocate a dmabuf from the
heap.

The interface is similar, but much simpler then IONs, only
providing an ALLOC ioctl.

Also, I've provided relatively simple system and cma heaps.

I've booted and tested these patches with AOSP on the HiKey960
using the kernel tree here:
  https://git.linaro.org/people/john.stultz/android-dev.git/log/?h=dev/dma-buf-heap

And the userspace changes here:
  https://android-review.googlesource.com/c/device/linaro/hikey/+/909436

Compared to ION, this patchset is missing the system-contig,
carveout and chunk heaps, as I don't have a device that uses
those, so I'm unable to do much useful validation there.
Additionally we have no upstream users of chunk or carveout,
and the system-contig has been deprecated in the common/andoid-*
kernels, so this should be ok.

I've also removed the stats accounting for now, since any such
accounting should be implemented by dma-buf core or the heaps
themselves.


New in v6:
* Number of cleanups and error path fixes suggested by Brian Starkey,
  many thanks for his close review and suggestions!


Outstanding concerns:
* Need to better understand various secure heap implementations.
  Some concern that heap private flags will be needed, but its
  also possible that dma-buf heaps can't solve everyone's needs,
  in which case, a vendor's secure buffer driver can implement
  their own dma-buf exporter. So I'm not too worried here.

Thoughts and feedback would be greatly appreciated!

thanks
-john

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: dri-devel@lists.freedesktop.org

Andrew F. Davis (1):
  dma-buf: Add dma-buf heaps framework

John Stultz (4):
  dma-buf: heaps: Add heap helpers
  dma-buf: heaps: Add system heap to dmabuf heaps
  dma-buf: heaps: Add CMA heap to dmabuf heaps
  kselftests: Add dma-heap test

 MAINTAINERS                                   |  18 ++
 drivers/dma-buf/Kconfig                       |  10 +
 drivers/dma-buf/Makefile                      |   2 +
 drivers/dma-buf/dma-heap.c                    | 249 +++++++++++++++++
 drivers/dma-buf/heaps/Kconfig                 |  14 +
 drivers/dma-buf/heaps/Makefile                |   4 +
 drivers/dma-buf/heaps/cma_heap.c              | 169 +++++++++++
 drivers/dma-buf/heaps/heap-helpers.c          | 262 ++++++++++++++++++
 drivers/dma-buf/heaps/heap-helpers.h          |  54 ++++
 drivers/dma-buf/heaps/system_heap.c           | 121 ++++++++
 include/linux/dma-heap.h                      |  59 ++++
 include/uapi/linux/dma-heap.h                 |  55 ++++
 tools/testing/selftests/dmabuf-heaps/Makefile |   9 +
 .../selftests/dmabuf-heaps/dmabuf-heap.c      | 234 ++++++++++++++++
 14 files changed, 1260 insertions(+)
 create mode 100644 drivers/dma-buf/dma-heap.c
 create mode 100644 drivers/dma-buf/heaps/Kconfig
 create mode 100644 drivers/dma-buf/heaps/Makefile
 create mode 100644 drivers/dma-buf/heaps/cma_heap.c
 create mode 100644 drivers/dma-buf/heaps/heap-helpers.c
 create mode 100644 drivers/dma-buf/heaps/heap-helpers.h
 create mode 100644 drivers/dma-buf/heaps/system_heap.c
 create mode 100644 include/linux/dma-heap.h
 create mode 100644 include/uapi/linux/dma-heap.h
 create mode 100644 tools/testing/selftests/dmabuf-heaps/Makefile
 create mode 100644 tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c

-- 
2.17.1


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

* [PATCH v6 1/5] dma-buf: Add dma-buf heaps framework
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
@ 2019-06-24 19:49 ` John Stultz
  2019-06-24 19:49   ` John Stultz
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: Andrew F. Davis, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel, John Stultz

From: "Andrew F. Davis" <afd@ti.com>

This framework allows a unified userspace interface for dma-buf
exporters, allowing userland to allocate specific types of memory
for use in dma-buf sharing.

Each heap is given its own device node, which a user can allocate
a dma-buf fd from using the DMA_HEAP_IOC_ALLOC.

This code is an evoluiton of the Android ION implementation,
and a big thanks is due to its authors/maintainers over time
for their effort:
  Rebecca Schultz Zavin, Colin Cross, Benjamin Gaignard,
  Laura Abbott, and many other contributors!

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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: I4af43a137ad34ff6f7da4d6b2864f3cd86fb7652
---
v2:
* Folded down fixes I had previously shared in implementing
  heaps
* Make flags a u64 (Suggested by Laura)
* Add PAGE_ALIGN() fix to the core alloc funciton
* IOCTL fixups suggested by Brian
* Added fixes suggested by Benjamin
* Removed core stats mgmt, as that should be implemented by
  per-heap code
* Changed alloc to return a dma-buf fd, rather than a buffer
  (as it simplifies error handling)
v3:
* Removed scare-quotes in MAINTAINERS email address
* Get rid of .release function as it didn't do anything (from
  Christoph)
* Renamed filp to file (suggested by Christoph)
* Split out ioctl handling to separate function (suggested by
  Christoph)
* Add comment documenting PAGE_ALIGN usage (suggested by Brian)
* Switch from idr to Xarray (suggested by Brian)
* Fixup cdev creation (suggested by Brian)
* Avoid EXPORT_SYMBOL until we finalize modules (suggested by
  Brian)
* Make struct dma_heap internal only (folded in from Andrew)
* Small cleanups suggested by GregKH
* Provide class->devnode callback to get consistent /dev/
  subdirectory naming (Suggested by Bjorn)
v4:
* Folded down dma-heap.h change that was in a following patch
* Added fd_flags entry to allocation structure and pass it
  through to heap code for use on dma-buf fd creation (suggested
  by Benjamin)
v5:
* Minor cleanups
v6:
* Improved error path handling, minor whitespace fixes, both
  suggested by Brian
---
 MAINTAINERS                   |  18 +++
 drivers/dma-buf/Kconfig       |   8 ++
 drivers/dma-buf/Makefile      |   1 +
 drivers/dma-buf/dma-heap.c    | 249 ++++++++++++++++++++++++++++++++++
 include/linux/dma-heap.h      |  59 ++++++++
 include/uapi/linux/dma-heap.h |  55 ++++++++
 6 files changed, 390 insertions(+)
 create mode 100644 drivers/dma-buf/dma-heap.c
 create mode 100644 include/linux/dma-heap.h
 create mode 100644 include/uapi/linux/dma-heap.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d0ed735994a5..851dbd006cdf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4813,6 +4813,24 @@ F:	include/linux/*fence.h
 F:	Documentation/driver-api/dma-buf.rst
 T:	git git://anongit.freedesktop.org/drm/drm-misc
 
+DMA-BUF HEAPS FRAMEWORK
+M:	Sumit Semwal <sumit.semwal@linaro.org>
+R:	Andrew F. Davis <afd@ti.com>
+R:	Benjamin Gaignard <benjamin.gaignard@linaro.org>
+R:	Liam Mark <lmark@codeaurora.org>
+R:	Laura Abbott <labbott@redhat.com>
+R:	Brian Starkey <Brian.Starkey@arm.com>
+R:	John Stultz <john.stultz@linaro.org>
+S:	Maintained
+L:	linux-media@vger.kernel.org
+L:	dri-devel@lists.freedesktop.org
+L:	linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
+F:	include/uapi/linux/dma-heap.h
+F:	include/linux/dma-heap.h
+F:	drivers/dma-buf/dma-heap.c
+F:	drivers/dma-buf/heaps/*
+T:	git git://anongit.freedesktop.org/drm/drm-misc
+
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
 M:	Vinod Koul <vkoul@kernel.org>
 L:	dmaengine@vger.kernel.org
diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
index d5f915830b68..9b93f86f597c 100644
--- a/drivers/dma-buf/Kconfig
+++ b/drivers/dma-buf/Kconfig
@@ -39,4 +39,12 @@ config UDMABUF
 	  A driver to let userspace turn memfd regions into dma-bufs.
 	  Qemu can use this to create host dmabufs for guest framebuffers.
 
+menuconfig DMABUF_HEAPS
+	bool "DMA-BUF Userland Memory Heaps"
+	select DMA_SHARED_BUFFER
+	help
+	  Choose this option to enable the DMA-BUF userland memory heaps,
+	  this allows userspace to allocate dma-bufs that can be shared between
+	  drivers.
+
 endmenu
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index e8c7310cb800..1cb3dd104825 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
 	 reservation.o seqno-fence.o
+obj-$(CONFIG_DMABUF_HEAPS)	+= dma-heap.o
 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/dma-heap.c b/drivers/dma-buf/dma-heap.c
new file mode 100644
index 000000000000..e44de7f69611
--- /dev/null
+++ b/drivers/dma-buf/dma-heap.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Framework for userspace DMA-BUF allocations
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2019 Linaro Ltd.
+ */
+
+#include <linux/cdev.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/err.h>
+#include <linux/xarray.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+#include <linux/dma-heap.h>
+#include <uapi/linux/dma-heap.h>
+
+#define DEVNAME "dma_heap"
+
+#define NUM_HEAP_MINORS 128
+
+/**
+ * struct dma_heap - represents a dmabuf heap in the system
+ * @name:		used for debugging/device-node name
+ * @ops:		ops struct for this heap
+ * @minor		minor number of this heap device
+ * @heap_devt		heap device node
+ * @heap_cdev		heap char device
+ *
+ * Represents a heap of memory from which buffers can be made.
+ */
+struct dma_heap {
+	const char *name;
+	struct dma_heap_ops *ops;
+	void *priv;
+	unsigned int minor;
+	dev_t heap_devt;
+	struct cdev heap_cdev;
+};
+
+static dev_t dma_heap_devt;
+static struct class *dma_heap_class;
+static DEFINE_XARRAY_ALLOC(dma_heap_minors);
+
+static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
+				 unsigned int fd_flags,
+				 unsigned int heap_flags)
+{
+	/*
+	 * Allocations from all heaps have to begin
+	 * and end on page boundaries.
+	 */
+	len = PAGE_ALIGN(len);
+	if (!len)
+		return -EINVAL;
+
+	return heap->ops->allocate(heap, len, fd_flags, heap_flags);
+}
+
+static int dma_heap_open(struct inode *inode, struct file *file)
+{
+	struct dma_heap *heap;
+
+	heap = xa_load(&dma_heap_minors, iminor(inode));
+	if (!heap) {
+		pr_err("dma_heap: minor %d unknown.\n", iminor(inode));
+		return -ENODEV;
+	}
+
+	/* instance data as context */
+	file->private_data = heap;
+	nonseekable_open(inode, file);
+
+	return 0;
+}
+
+static long dma_heap_ioctl_allocate(struct file *file, unsigned long arg)
+{
+	struct dma_heap_allocation_data heap_allocation;
+	struct dma_heap *heap = file->private_data;
+	int fd;
+
+	if (copy_from_user(&heap_allocation, (void __user *)arg,
+			   sizeof(heap_allocation)))
+		return -EFAULT;
+
+	if (heap_allocation.fd ||
+	    heap_allocation.reserved0 ||
+	    heap_allocation.reserved1) {
+		pr_warn_once("dma_heap: ioctl data not valid\n");
+		return -EINVAL;
+	}
+
+	if (heap_allocation.fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) {
+		pr_warn_once("dma_heap: fd_flags has invalid or unsupported flags set\n");
+		return -EINVAL;
+	}
+
+	if (heap_allocation.heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) {
+		pr_warn_once("dma_heap: heap flags has invalid or unsupported flags set\n");
+		return -EINVAL;
+	}
+
+
+	fd = dma_heap_buffer_alloc(heap, heap_allocation.len,
+				   heap_allocation.fd_flags,
+				   heap_allocation.heap_flags);
+	if (fd < 0)
+		return fd;
+
+	heap_allocation.fd = fd;
+
+	if (copy_to_user((void __user *)arg, &heap_allocation,
+			 sizeof(heap_allocation))) {
+		ksys_close(fd);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static long dma_heap_ioctl(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case DMA_HEAP_IOC_ALLOC:
+		ret = dma_heap_ioctl_allocate(file, arg);
+		break;
+	default:
+		return -ENOTTY;
+	}
+
+	return ret;
+}
+
+static const struct file_operations dma_heap_fops = {
+	.owner          = THIS_MODULE,
+	.open		= dma_heap_open,
+	.unlocked_ioctl = dma_heap_ioctl,
+};
+
+/**
+ * dma_heap_get_data() - get per-subdriver data for the heap
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The per-subdriver data for the heap.
+ */
+void *dma_heap_get_data(struct dma_heap *heap)
+{
+	return heap->priv;
+}
+
+struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info)
+{
+	struct dma_heap *heap, *err_ret;
+	struct device *dev_ret;
+	int ret;
+
+	if (!exp_info->name || !strcmp(exp_info->name, "")) {
+		pr_err("dma_heap: Cannot add heap without a name\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!exp_info->ops || !exp_info->ops->allocate) {
+		pr_err("dma_heap: Cannot add heap with invalid ops struct\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
+	if (!heap)
+		return ERR_PTR(-ENOMEM);
+
+	heap->name = exp_info->name;
+	heap->ops = exp_info->ops;
+	heap->priv = exp_info->priv;
+
+	/* Find unused minor number */
+	ret = xa_alloc(&dma_heap_minors, &heap->minor, heap,
+			XA_LIMIT(0, NUM_HEAP_MINORS - 1), GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("dma_heap: Unable to get minor number for heap\n");
+		err_ret = ERR_PTR(ret);
+		goto err0;
+	}
+
+	/* Create device */
+	heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor);
+
+	cdev_init(&heap->heap_cdev, &dma_heap_fops);
+	ret = cdev_add(&heap->heap_cdev, heap->heap_devt, 1);
+	if (ret < 0) {
+		pr_err("dma_heap: Unable to add char device\n");
+		err_ret = ERR_PTR(ret);
+		goto err1;
+	}
+
+	dev_ret = device_create(dma_heap_class,
+				NULL,
+				heap->heap_devt,
+				NULL,
+				heap->name);
+	if (IS_ERR(dev_ret)) {
+		pr_err("dma_heap: Unable to create device\n");
+		err_ret = (struct dma_heap *)dev_ret;
+		goto err2;
+	}
+
+	return heap;
+
+err2:
+	cdev_del(&heap->heap_cdev);
+err1:
+	xa_erase(&dma_heap_minors, heap->minor);
+err0:
+	kfree(heap);
+	return err_ret;
+
+}
+
+static char *dma_heap_devnode(struct device *dev, umode_t *mode)
+{
+	return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
+}
+
+static int dma_heap_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&dma_heap_devt, 0, NUM_HEAP_MINORS, DEVNAME);
+	if (ret)
+		return ret;
+
+	dma_heap_class = class_create(THIS_MODULE, DEVNAME);
+	if (IS_ERR(dma_heap_class)) {
+		unregister_chrdev_region(dma_heap_devt, NUM_HEAP_MINORS);
+		return PTR_ERR(dma_heap_class);
+	}
+	dma_heap_class->devnode = dma_heap_devnode;
+
+	return 0;
+}
+subsys_initcall(dma_heap_init);
diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h
new file mode 100644
index 000000000000..7a1b633ac02f
--- /dev/null
+++ b/include/linux/dma-heap.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * DMABUF Heaps Allocation Infrastructure
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2019 Linaro Ltd.
+ */
+
+#ifndef _DMA_HEAPS_H
+#define _DMA_HEAPS_H
+
+#include <linux/cdev.h>
+#include <linux/types.h>
+
+struct dma_heap;
+
+/**
+ * struct dma_heap_ops - ops to operate on a given heap
+ * @allocate:		allocate dmabuf and return fd
+ *
+ * allocate returns dmabuf fd  on success, -errno on error.
+ */
+struct dma_heap_ops {
+	int (*allocate)(struct dma_heap *heap,
+			unsigned long len,
+			unsigned long fd_flags,
+			unsigned long heap_flags);
+};
+
+/**
+ * struct dma_heap_export_info - information needed to export a new dmabuf heap
+ * @name:	used for debugging/device-node name
+ * @ops:	ops struct for this heap
+ * @priv:	heap exporter private data
+ *
+ * Information needed to export a new dmabuf heap.
+ */
+struct dma_heap_export_info {
+	const char *name;
+	struct dma_heap_ops *ops;
+	void *priv;
+};
+
+/**
+ * dma_heap_get_data() - get per-heap driver data
+ * @heap: DMA-Heap to retrieve private data for
+ *
+ * Returns:
+ * The per-heap data for the heap.
+ */
+void *dma_heap_get_data(struct dma_heap *heap);
+
+/**
+ * dma_heap_add - adds a heap to dmabuf heaps
+ * @exp_info:		information needed to register this heap
+ */
+struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
+
+#endif /* _DMA_HEAPS_H */
diff --git a/include/uapi/linux/dma-heap.h b/include/uapi/linux/dma-heap.h
new file mode 100644
index 000000000000..6ce5cc68d238
--- /dev/null
+++ b/include/uapi/linux/dma-heap.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * DMABUF Heaps Userspace API
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2019 Linaro Ltd.
+ */
+#ifndef _UAPI_LINUX_DMABUF_POOL_H
+#define _UAPI_LINUX_DMABUF_POOL_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * DOC: DMABUF Heaps Userspace API
+ */
+
+/* Valid FD_FLAGS are O_CLOEXEC, O_RDONLY, O_WRONLY, O_RDWR */
+#define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE)
+
+/* Currently no heap flags */
+#define DMA_HEAP_VALID_HEAP_FLAGS (0)
+
+/**
+ * struct dma_heap_allocation_data - metadata passed from userspace for
+ *                                      allocations
+ * @len:		size of the allocation
+ * @fd:			will be populated with a fd which provdes the
+ *			handle to the allocated dma-buf
+ * @fd_flags:		file descriptor flags used when allocating
+ * @heap_flags:		flags passed to heap
+ *
+ * Provided by userspace as an argument to the ioctl
+ */
+struct dma_heap_allocation_data {
+	__u64 len;
+	__u32 fd;
+	__u32 fd_flags;
+	__u64 heap_flags;
+	__u32 reserved0;
+	__u32 reserved1;
+};
+
+#define DMA_HEAP_IOC_MAGIC		'H'
+
+/**
+ * DOC: DMA_HEAP_IOC_ALLOC - allocate memory from pool
+ *
+ * Takes an dma_heap_allocation_data struct and returns it with the fd field
+ * populated with the dmabuf handle of the allocation.
+ */
+#define DMA_HEAP_IOC_ALLOC	_IOWR(DMA_HEAP_IOC_MAGIC, 0, \
+				      struct dma_heap_allocation_data)
+
+#endif /* _UAPI_LINUX_DMABUF_POOL_H */
-- 
2.17.1


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

* [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
@ 2019-06-24 19:49   ` John Stultz
  2019-06-24 19:49   ` John Stultz
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Xu YiPing, Chenfeng (puck),
	butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: I48d43656e7783f266d877e363116b5187639f996
---
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
---
 drivers/dma-buf/Makefile             |   1 +
 drivers/dma-buf/heaps/Makefile       |   2 +
 drivers/dma-buf/heaps/heap-helpers.c | 262 +++++++++++++++++++++++++++
 drivers/dma-buf/heaps/heap-helpers.h |  54 ++++++
 4 files changed, 319 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 1cb3dd104825..e3e3dca29e46 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
 	 reservation.o seqno-fence.o
+obj-$(CONFIG_DMABUF_HEAPS)	+= heaps/
 obj-$(CONFIG_DMABUF_HEAPS)	+= dma-heap.o
 obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
 obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.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..fba1895f3bf0
--- /dev/null
+++ b/drivers/dma-buf/heaps/heap-helpers.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/uaccess.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->private_flags = 0;
+	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;
+}
+
+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 dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	if (buffer->vmap_cnt > 0) {
+		WARN("%s: buffer still mapped in the kernel\n",
+			     __func__);
+		vunmap(buffer->vaddr);
+	}
+
+	buffer->free(buffer);
+}
+
+static void *dma_heap_buffer_vmap_get(struct dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	void *vaddr;
+
+	if (buffer->vmap_cnt) {
+		buffer->vmap_cnt++;
+		return buffer->vaddr;
+	}
+	vaddr = dma_heap_map_kernel(buffer);
+	if (WARN_ONCE(!vaddr,
+		      "heap->ops->map_kernel should return ERR_PTR on error"))
+		return ERR_PTR(-EINVAL);
+	if (IS_ERR(vaddr))
+		return vaddr;
+	buffer->vaddr = vaddr;
+	buffer->vmap_cnt++;
+	return vaddr;
+}
+
+static void dma_heap_buffer_vmap_put(struct dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	if (!--buffer->vmap_cnt) {
+		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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	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;
+
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	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 dma_heap_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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	struct dma_heaps_attachment *a;
+	int ret = 0;
+
+	mutex_lock(&buffer->lock);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	struct dma_heaps_attachment *a;
+
+	mutex_lock(&buffer->lock);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	void *vaddr;
+
+	mutex_lock(&buffer->lock);
+	vaddr = dma_heap_buffer_vmap_get(heap_buffer);
+	mutex_unlock(&buffer->lock);
+
+	return vaddr;
+}
+
+static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+	struct dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	mutex_lock(&buffer->lock);
+	dma_heap_buffer_vmap_put(heap_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..7e0a82b11c9e
--- /dev/null
+++ b/drivers/dma-buf/heaps/heap-helpers.h
@@ -0,0 +1,54 @@
+/* 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 dma_heap_buffer - metadata for a particular buffer
+ * @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
+ */
+struct dma_heap_buffer {
+	struct dma_heap *heap;
+	struct dma_buf *dmabuf;
+	size_t size;
+	unsigned long flags;
+};
+
+struct heap_helper_buffer {
+	struct dma_heap_buffer heap_buffer;
+
+	unsigned long private_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);
+};
+
+static inline struct heap_helper_buffer *to_helper_buffer(
+						struct dma_heap_buffer *h)
+{
+	return container_of(h, struct heap_helper_buffer, heap_buffer);
+}
+
+void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
+				 void (*free)(struct heap_helper_buffer *));
+extern const struct dma_buf_ops heap_helper_ops;
+
+#endif /* _HEAP_HELPERS_H */
-- 
2.17.1


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

* [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-06-24 19:49   ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Vincent Donnefort,
	Chenfeng (puck),
	dri-devel, Chenbo Feng, Alistair Strachan, Liam Mark,
	Christoph Hellwig, Xiaqing (A),
	Andrew F . Davis, Pratik Patel, butao

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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: I48d43656e7783f266d877e363116b5187639f996
---
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
---
 drivers/dma-buf/Makefile             |   1 +
 drivers/dma-buf/heaps/Makefile       |   2 +
 drivers/dma-buf/heaps/heap-helpers.c | 262 +++++++++++++++++++++++++++
 drivers/dma-buf/heaps/heap-helpers.h |  54 ++++++
 4 files changed, 319 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 1cb3dd104825..e3e3dca29e46 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \
 	 reservation.o seqno-fence.o
+obj-$(CONFIG_DMABUF_HEAPS)	+= heaps/
 obj-$(CONFIG_DMABUF_HEAPS)	+= dma-heap.o
 obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
 obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.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..fba1895f3bf0
--- /dev/null
+++ b/drivers/dma-buf/heaps/heap-helpers.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/uaccess.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->private_flags = 0;
+	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;
+}
+
+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 dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	if (buffer->vmap_cnt > 0) {
+		WARN("%s: buffer still mapped in the kernel\n",
+			     __func__);
+		vunmap(buffer->vaddr);
+	}
+
+	buffer->free(buffer);
+}
+
+static void *dma_heap_buffer_vmap_get(struct dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	void *vaddr;
+
+	if (buffer->vmap_cnt) {
+		buffer->vmap_cnt++;
+		return buffer->vaddr;
+	}
+	vaddr = dma_heap_map_kernel(buffer);
+	if (WARN_ONCE(!vaddr,
+		      "heap->ops->map_kernel should return ERR_PTR on error"))
+		return ERR_PTR(-EINVAL);
+	if (IS_ERR(vaddr))
+		return vaddr;
+	buffer->vaddr = vaddr;
+	buffer->vmap_cnt++;
+	return vaddr;
+}
+
+static void dma_heap_buffer_vmap_put(struct dma_heap_buffer *heap_buffer)
+{
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	if (!--buffer->vmap_cnt) {
+		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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	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;
+
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	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 dma_heap_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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	struct dma_heaps_attachment *a;
+	int ret = 0;
+
+	mutex_lock(&buffer->lock);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	struct dma_heaps_attachment *a;
+
+	mutex_lock(&buffer->lock);
+	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 dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+	void *vaddr;
+
+	mutex_lock(&buffer->lock);
+	vaddr = dma_heap_buffer_vmap_get(heap_buffer);
+	mutex_unlock(&buffer->lock);
+
+	return vaddr;
+}
+
+static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr)
+{
+	struct dma_heap_buffer *heap_buffer = dmabuf->priv;
+	struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer);
+
+	mutex_lock(&buffer->lock);
+	dma_heap_buffer_vmap_put(heap_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..7e0a82b11c9e
--- /dev/null
+++ b/drivers/dma-buf/heaps/heap-helpers.h
@@ -0,0 +1,54 @@
+/* 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 dma_heap_buffer - metadata for a particular buffer
+ * @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
+ */
+struct dma_heap_buffer {
+	struct dma_heap *heap;
+	struct dma_buf *dmabuf;
+	size_t size;
+	unsigned long flags;
+};
+
+struct heap_helper_buffer {
+	struct dma_heap_buffer heap_buffer;
+
+	unsigned long private_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);
+};
+
+static inline struct heap_helper_buffer *to_helper_buffer(
+						struct dma_heap_buffer *h)
+{
+	return container_of(h, struct heap_helper_buffer, heap_buffer);
+}
+
+void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
+				 void (*free)(struct heap_helper_buffer *));
+extern const struct dma_buf_ops heap_helper_ops;
+
+#endif /* _HEAP_HELPERS_H */
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v6 3/5] dma-buf: heaps: Add system heap to dmabuf heaps
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
  2019-06-24 19:49 ` [PATCH v6 1/5] dma-buf: Add dma-buf heaps framework John Stultz
  2019-06-24 19:49   ` John Stultz
@ 2019-06-24 19:49 ` John Stultz
  2019-06-24 19:49 ` [PATCH v6 4/5] dma-buf: heaps: Add CMA " John Stultz
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Xu YiPing, Chenfeng (puck),
	butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: I4dc5ff54ccb1f7ca3ac8675661114ca33813654b
---
v2:
* Switch allocate to return dmabuf fd
* Simplify init code
* Checkpatch fixups
* Droped dead system-contig code
v3:
* Whitespace fixups from Benjamin
* Make sure we're zeroing the allocated pages (from Liam)
* Use PAGE_ALIGN() consistently (suggested by Brian)
* Fold in new registration style from Andrew
* Avoid needless dynamic allocation of sys_heap (suggested by
  Christoph)
* Minor cleanups
* Folded in changes from Andrew to use simplified page list
  from the heap helpers
v4:
* Optimization to allocate pages in chunks, similar to old
  pagepool code
* Use fd_flags when creating dmabuf fd (Suggested by Benjamin)
v5:
* Back out large order page allocations (was leaking memory,
  as the page array didn't properly track order size)
v6:
* Minor whitespace change suggested by Brian
* Remove unused variable
---
 drivers/dma-buf/Kconfig             |   2 +
 drivers/dma-buf/heaps/Kconfig       |   6 ++
 drivers/dma-buf/heaps/Makefile      |   1 +
 drivers/dma-buf/heaps/system_heap.c | 121 ++++++++++++++++++++++++++++
 4 files changed, 130 insertions(+)
 create mode 100644 drivers/dma-buf/heaps/Kconfig
 create mode 100644 drivers/dma-buf/heaps/system_heap.c

diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
index 9b93f86f597c..434cfe646dad 100644
--- a/drivers/dma-buf/Kconfig
+++ b/drivers/dma-buf/Kconfig
@@ -47,4 +47,6 @@ menuconfig DMABUF_HEAPS
 	  this allows userspace to allocate dma-bufs that can be shared between
 	  drivers.
 
+source "drivers/dma-buf/heaps/Kconfig"
+
 endmenu
diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
new file mode 100644
index 000000000000..205052744169
--- /dev/null
+++ b/drivers/dma-buf/heaps/Kconfig
@@ -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.
diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
index de49898112db..d1808eca2581 100644
--- a/drivers/dma-buf/heaps/Makefile
+++ b/drivers/dma-buf/heaps/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y					+= heap-helpers.o
+obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)	+= system_heap.o
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
new file mode 100644
index 000000000000..6a16806181c2
--- /dev/null
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMABUF System heap exporter
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (C) 2019 Linaro Ltd.
+ */
+
+#include <asm/page.h>
+#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/scatterlist.h>
+#include <linux/slab.h>
+
+#include "heap-helpers.h"
+
+struct system_heap {
+	struct dma_heap *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;
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	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_buffer.flags = heap_flags;
+	helper_buffer->heap_buffer.heap = heap;
+	helper_buffer->heap_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++) {
+		helper_buffer->pages[pg] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!helper_buffer->pages[pg])
+			goto err1;
+	}
+
+	/* create the dmabuf */
+	exp_info.ops = &heap_helper_ops;
+	exp_info.size = len;
+	exp_info.flags = fd_flags;
+	exp_info.priv = &helper_buffer->heap_buffer;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf)) {
+		ret = PTR_ERR(dmabuf);
+		goto err1;
+	}
+
+	helper_buffer->heap_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 -ENOMEM;
+}
+
+static 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 = &sys_heap;
+
+	sys_heap.heap = dma_heap_add(&exp_info);
+	if (IS_ERR(sys_heap.heap))
+		ret = PTR_ERR(sys_heap.heap);
+
+	return ret;
+}
+device_initcall(system_heap_create);
-- 
2.17.1


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

* [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
                   ` (2 preceding siblings ...)
  2019-06-24 19:49 ` [PATCH v6 3/5] dma-buf: heaps: Add system heap to dmabuf heaps John Stultz
@ 2019-06-24 19:49 ` John Stultz
  2019-07-18 10:08   ` Christoph Hellwig
  2019-06-24 19:49   ` John Stultz
  2019-07-01 21:45 ` [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) Laura Abbott
  5 siblings, 1 reply; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Xu YiPing, Chenfeng (puck),
	butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

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 <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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: Ic2b0c5dfc0dbaff5245bd1c50170c64b06c73051
---
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
v4:
* Use the fd_flags when creating dmabuf fd (Suggested by
  Benjamin)
* Use precalculated pagecount (Suggested by Andrew)
v6:
* Changed variable names to improve clarity, as suggested
  by Brian
---
 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 000000000000..d2b10878b60b
--- /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: <benjamin.gaignard@linaro.org> for ST-Ericsson.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/cma.h>
+#include <linux/scatterlist.h>
+#include <linux/highmem.h>
+
+#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 *cma_pages = buffer->priv_virt;
+
+	/* free page list */
+	kfree(buffer->pages);
+	/* release memory */
+	cma_release(cma_heap->cma, 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 *cma_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;
+
+	cma_pages = cma_alloc(cma_heap->cma, nr_pages, align, false);
+	if (!cma_pages)
+		goto free_buf;
+
+	if (PageHighMem(cma_pages)) {
+		unsigned long nr_clear_pages = nr_pages;
+		struct page *page = cma_pages;
+
+		while (nr_clear_pages > 0) {
+			void *vaddr = kmap_atomic(page);
+
+			memset(vaddr, 0, PAGE_SIZE);
+			kunmap_atomic(vaddr);
+			page++;
+			nr_clear_pages--;
+		}
+	} else {
+		memset(page_address(cma_pages), 0, size);
+	}
+
+	helper_buffer->pagecount = nr_pages;
+	helper_buffer->pages = kmalloc_array(helper_buffer->pagecount,
+					     sizeof(*helper_buffer->pages),
+					     GFP_KERNEL);
+	if (!helper_buffer->pages) {
+		ret = -ENOMEM;
+		goto free_cma;
+	}
+
+	for (pg = 0; pg < helper_buffer->pagecount; pg++) {
+		helper_buffer->pages[pg] = &cma_pages[pg];
+		if (!helper_buffer->pages[pg])
+			goto free_pages;
+	}
+
+	/* create the dmabuf */
+	exp_info.ops = &heap_helper_ops;
+	exp_info.size = len;
+	exp_info.flags = fd_flags;
+	exp_info.priv = &helper_buffer->heap_buffer;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf)) {
+		ret = PTR_ERR(dmabuf);
+		goto free_pages;
+	}
+
+	helper_buffer->heap_buffer.dmabuf = dmabuf;
+	helper_buffer->priv_virt = cma_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;
+
+free_pages:
+	kfree(helper_buffer->pages);
+free_cma:
+	cma_release(cma_heap->cma, cma_pages, nr_pages);
+free_buf:
+	kfree(helper_buffer);
+	return ret;
+}
+
+static struct dma_heap_ops cma_heap_ops = {
+	.allocate = cma_heap_allocate,
+};
+
+static int __add_cma_heap(struct cma *cma, void *data)
+{
+	struct cma_heap *cma_heap;
+	struct dma_heap_export_info exp_info;
+
+	cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL);
+	if (!cma_heap)
+		return -ENOMEM;
+	cma_heap->cma = cma;
+
+	exp_info.name = cma_get_name(cma);
+	exp_info.ops = &cma_heap_ops;
+	exp_info.priv = cma_heap;
+
+	cma_heap->heap = dma_heap_add(&exp_info);
+	if (IS_ERR(cma_heap->heap)) {
+		int ret = PTR_ERR(cma_heap->heap);
+
+		kfree(cma_heap);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int add_cma_heaps(void)
+{
+	cma_for_each_area(__add_cma_heap, NULL);
+	return 0;
+}
+device_initcall(add_cma_heaps);
-- 
2.17.1


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

* [PATCH v6 5/5] kselftests: Add dma-heap test
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
@ 2019-06-24 19:49   ` John Stultz
  2019-06-24 19:49   ` John Stultz
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

Add very trivial allocation and import test for dma-heaps,
utilizing the vgem driver as a test importer.

A good chunk of this code taken from:
  tools/testing/selftests/android/ion/ionmap_test.c
  Originally by 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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: Ib98569fdda6378eb086b8092fb5d6bd419b8d431
---
v2:
* Switched to use reworked dma-heap apis
v3:
* Add simple mmap
* Utilize dma-buf testdev to test importing
v4:
* Rework to use vgem
* Pass in fd_flags to match interface changes
* Skip . and .. dirs
v6:
* Number of style/cleanups suggested by Brian
---
 tools/testing/selftests/dmabuf-heaps/Makefile |   9 +
 .../selftests/dmabuf-heaps/dmabuf-heap.c      | 234 ++++++++++++++++++
 2 files changed, 243 insertions(+)
 create mode 100644 tools/testing/selftests/dmabuf-heaps/Makefile
 create mode 100644 tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c

diff --git a/tools/testing/selftests/dmabuf-heaps/Makefile b/tools/testing/selftests/dmabuf-heaps/Makefile
new file mode 100644
index 000000000000..8c4c36e2972d
--- /dev/null
+++ b/tools/testing/selftests/dmabuf-heaps/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+CFLAGS += -static -O3 -Wl,-no-as-needed -Wall
+#LDLIBS += -lrt -lpthread -lm
+
+# these are all "safe" tests that don't modify
+# system time or require escalated privileges
+TEST_GEN_PROGS = dmabuf-heap
+
+include ../lib.mk
diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
new file mode 100644
index 000000000000..1e93b6fbe459
--- /dev/null
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/dma-buf.h>
+#include <drm/drm.h>
+
+
+#include "../../../../include/uapi/linux/dma-heap.h"
+
+#define DEVPATH "/dev/dma_heap"
+
+static int check_vgem(int fd)
+{
+	drm_version_t version = { 0 };
+	char name[5];
+	int ret;
+
+	version.name_len = 4;
+	version.name = name;
+
+	ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
+	if (ret)
+		return 0;
+
+	return !strcmp(name, "vgem");
+}
+
+static int open_vgem(void)
+{
+	int i, fd;
+	const char *drmstr = "/dev/dri/card";
+
+	fd = -1;
+	for (i = 0; i < 16; i++) {
+		char name[80];
+
+		sprintf(name, "%s%u", drmstr, i);
+
+		fd = open(name, O_RDWR);
+		if (fd < 0)
+			continue;
+
+		if (!check_vgem(fd)) {
+			close(fd);
+			continue;
+		} else {
+			break;
+		}
+
+	}
+	return fd;
+}
+
+static int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
+{
+	struct drm_prime_handle import_handle = {
+		.fd = dma_buf_fd,
+		.flags = 0,
+		.handle = 0,
+	 };
+	int ret;
+
+	ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
+	if (ret == 0)
+		*handle = import_handle.handle;
+	return ret;
+}
+
+static void close_handle(int vgem_fd, uint32_t handle)
+{
+	struct drm_gem_close close = {
+		.handle = handle,
+	};
+
+	ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
+}
+
+
+static int dmabuf_heap_open(char *name)
+{
+	int ret, fd;
+	char buf[256];
+
+	ret = sprintf(buf, "%s/%s", DEVPATH, name);
+	if (ret < 0) {
+		printf("sprintf failed!\n");
+		return ret;
+	}
+
+	fd = open(buf, O_RDWR);
+	if (fd < 0)
+		printf("open %s failed!\n", buf);
+	return fd;
+}
+
+static int dmabuf_heap_alloc(int fd, size_t len, unsigned int flags, int *dmabuf_fd)
+{
+	struct dma_heap_allocation_data data = {
+		.len = len,
+		.fd_flags = O_RDWR | O_CLOEXEC,
+		.heap_flags = flags,
+	};
+	int ret;
+
+	if (dmabuf_fd == NULL)
+		return -EINVAL;
+
+	ret = ioctl(fd, DMA_HEAP_IOC_ALLOC, &data);
+	if (ret < 0)
+		return ret;
+	*dmabuf_fd = (int)data.fd;
+	return ret;
+}
+
+static void dmabuf_sync(int fd, int start_stop)
+{
+	struct dma_buf_sync sync = {
+		.flags = start_stop | DMA_BUF_SYNC_RW,
+	};
+	int ret;
+
+	ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
+	if (ret)
+		printf("sync failed %d\n", errno);
+}
+
+#define ONE_MEG (1024*1024)
+
+static void do_test(char *heap_name)
+{
+	int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
+	uint32_t handle = 0;
+	void *p = NULL;
+	int ret;
+
+	printf("Testing heap: %s\n", heap_name);
+
+	heap_fd = dmabuf_heap_open(heap_name);
+	if (heap_fd < 0)
+		return;
+
+	printf("Allocating 1 MEG\n");
+	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
+	if (ret) {
+		printf("Allocation Failed!\n");
+		goto out;
+	}
+	/* mmap and write a simple pattern */
+	p = mmap(NULL,
+		 ONE_MEG,
+		 PROT_READ | PROT_WRITE,
+		 MAP_SHARED,
+		 dmabuf_fd,
+		 0);
+	if (p == MAP_FAILED) {
+		printf("mmap() failed: %m\n");
+		goto out;
+	}
+	printf("mmap passed\n");
+
+
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+
+	memset(p, 1, ONE_MEG / 2);
+	memset((char *)p + ONE_MEG / 2, 0, ONE_MEG / 2);
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+
+	importer_fd = open_vgem();
+	if (importer_fd < 0) {
+		ret = importer_fd;
+		printf("Failed to open vgem\n");
+		goto out;
+	}
+
+	ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
+	if (ret < 0) {
+		printf("Failed to import buffer\n");
+		goto out;
+	}
+	printf("import passed\n");
+
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+	memset(p, 0xff, ONE_MEG);
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+	printf("syncs passed\n");
+
+	close_handle(importer_fd, handle);
+
+out:
+	if (p)
+		munmap(p, ONE_MEG);
+	if (importer_fd >= 0)
+		close(importer_fd);
+	if (dmabuf_fd >= 0)
+		close(dmabuf_fd);
+	if (heap_fd >= 0)
+		close(heap_fd);
+}
+
+
+int main(void)
+{
+	DIR *d;
+	struct dirent *dir;
+
+	d = opendir(DEVPATH);
+	if (!d) {
+		printf("No %s directory?\n", DEVPATH);
+		return -1;
+	}
+
+	while ((dir = readdir(d)) != NULL) {
+		if (!strncmp(dir->d_name, ".", 2))
+			continue;
+		if (!strncmp(dir->d_name, "..", 3))
+			continue;
+
+		do_test(dir->d_name);
+	}
+	closedir(d);
+
+	return 0;
+}
-- 
2.17.1


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

* [PATCH v6 5/5] kselftests: Add dma-heap test
@ 2019-06-24 19:49   ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-06-24 19:49 UTC (permalink / raw)
  To: lkml
  Cc: Yudongbin, Xu YiPing, Vincent Donnefort, Chenfeng (puck),
	dri-devel, Chenbo Feng, Alistair Strachan, Liam Mark,
	Christoph Hellwig, Xiaqing (A),
	Andrew F . Davis, Sudipto Paul, Pratik Patel, butao

Add very trivial allocation and import test for dma-heaps,
utilizing the vgem driver as a test importer.

A good chunk of this code taken from:
  tools/testing/selftests/android/ion/ionmap_test.c
  Originally by 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: Xu YiPing <xuyiping@hisilicon.com>
Cc: "Chenfeng (puck)" <puck.chen@hisilicon.com>
Cc: butao <butao@hisilicon.com>
Cc: "Xiaqing (A)" <saberlily.xia@hisilicon.com>
Cc: Yudongbin <yudongbin@hisilicon.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Chenbo Feng <fengc@google.com>
Cc: Alistair Strachan <astrachan@google.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Change-Id: Ib98569fdda6378eb086b8092fb5d6bd419b8d431
---
v2:
* Switched to use reworked dma-heap apis
v3:
* Add simple mmap
* Utilize dma-buf testdev to test importing
v4:
* Rework to use vgem
* Pass in fd_flags to match interface changes
* Skip . and .. dirs
v6:
* Number of style/cleanups suggested by Brian
---
 tools/testing/selftests/dmabuf-heaps/Makefile |   9 +
 .../selftests/dmabuf-heaps/dmabuf-heap.c      | 234 ++++++++++++++++++
 2 files changed, 243 insertions(+)
 create mode 100644 tools/testing/selftests/dmabuf-heaps/Makefile
 create mode 100644 tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c

diff --git a/tools/testing/selftests/dmabuf-heaps/Makefile b/tools/testing/selftests/dmabuf-heaps/Makefile
new file mode 100644
index 000000000000..8c4c36e2972d
--- /dev/null
+++ b/tools/testing/selftests/dmabuf-heaps/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+CFLAGS += -static -O3 -Wl,-no-as-needed -Wall
+#LDLIBS += -lrt -lpthread -lm
+
+# these are all "safe" tests that don't modify
+# system time or require escalated privileges
+TEST_GEN_PROGS = dmabuf-heap
+
+include ../lib.mk
diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
new file mode 100644
index 000000000000..1e93b6fbe459
--- /dev/null
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+#include <linux/dma-buf.h>
+#include <drm/drm.h>
+
+
+#include "../../../../include/uapi/linux/dma-heap.h"
+
+#define DEVPATH "/dev/dma_heap"
+
+static int check_vgem(int fd)
+{
+	drm_version_t version = { 0 };
+	char name[5];
+	int ret;
+
+	version.name_len = 4;
+	version.name = name;
+
+	ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
+	if (ret)
+		return 0;
+
+	return !strcmp(name, "vgem");
+}
+
+static int open_vgem(void)
+{
+	int i, fd;
+	const char *drmstr = "/dev/dri/card";
+
+	fd = -1;
+	for (i = 0; i < 16; i++) {
+		char name[80];
+
+		sprintf(name, "%s%u", drmstr, i);
+
+		fd = open(name, O_RDWR);
+		if (fd < 0)
+			continue;
+
+		if (!check_vgem(fd)) {
+			close(fd);
+			continue;
+		} else {
+			break;
+		}
+
+	}
+	return fd;
+}
+
+static int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
+{
+	struct drm_prime_handle import_handle = {
+		.fd = dma_buf_fd,
+		.flags = 0,
+		.handle = 0,
+	 };
+	int ret;
+
+	ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
+	if (ret == 0)
+		*handle = import_handle.handle;
+	return ret;
+}
+
+static void close_handle(int vgem_fd, uint32_t handle)
+{
+	struct drm_gem_close close = {
+		.handle = handle,
+	};
+
+	ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
+}
+
+
+static int dmabuf_heap_open(char *name)
+{
+	int ret, fd;
+	char buf[256];
+
+	ret = sprintf(buf, "%s/%s", DEVPATH, name);
+	if (ret < 0) {
+		printf("sprintf failed!\n");
+		return ret;
+	}
+
+	fd = open(buf, O_RDWR);
+	if (fd < 0)
+		printf("open %s failed!\n", buf);
+	return fd;
+}
+
+static int dmabuf_heap_alloc(int fd, size_t len, unsigned int flags, int *dmabuf_fd)
+{
+	struct dma_heap_allocation_data data = {
+		.len = len,
+		.fd_flags = O_RDWR | O_CLOEXEC,
+		.heap_flags = flags,
+	};
+	int ret;
+
+	if (dmabuf_fd == NULL)
+		return -EINVAL;
+
+	ret = ioctl(fd, DMA_HEAP_IOC_ALLOC, &data);
+	if (ret < 0)
+		return ret;
+	*dmabuf_fd = (int)data.fd;
+	return ret;
+}
+
+static void dmabuf_sync(int fd, int start_stop)
+{
+	struct dma_buf_sync sync = {
+		.flags = start_stop | DMA_BUF_SYNC_RW,
+	};
+	int ret;
+
+	ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
+	if (ret)
+		printf("sync failed %d\n", errno);
+}
+
+#define ONE_MEG (1024*1024)
+
+static void do_test(char *heap_name)
+{
+	int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
+	uint32_t handle = 0;
+	void *p = NULL;
+	int ret;
+
+	printf("Testing heap: %s\n", heap_name);
+
+	heap_fd = dmabuf_heap_open(heap_name);
+	if (heap_fd < 0)
+		return;
+
+	printf("Allocating 1 MEG\n");
+	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
+	if (ret) {
+		printf("Allocation Failed!\n");
+		goto out;
+	}
+	/* mmap and write a simple pattern */
+	p = mmap(NULL,
+		 ONE_MEG,
+		 PROT_READ | PROT_WRITE,
+		 MAP_SHARED,
+		 dmabuf_fd,
+		 0);
+	if (p == MAP_FAILED) {
+		printf("mmap() failed: %m\n");
+		goto out;
+	}
+	printf("mmap passed\n");
+
+
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+
+	memset(p, 1, ONE_MEG / 2);
+	memset((char *)p + ONE_MEG / 2, 0, ONE_MEG / 2);
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+
+	importer_fd = open_vgem();
+	if (importer_fd < 0) {
+		ret = importer_fd;
+		printf("Failed to open vgem\n");
+		goto out;
+	}
+
+	ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
+	if (ret < 0) {
+		printf("Failed to import buffer\n");
+		goto out;
+	}
+	printf("import passed\n");
+
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
+	memset(p, 0xff, ONE_MEG);
+	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
+	printf("syncs passed\n");
+
+	close_handle(importer_fd, handle);
+
+out:
+	if (p)
+		munmap(p, ONE_MEG);
+	if (importer_fd >= 0)
+		close(importer_fd);
+	if (dmabuf_fd >= 0)
+		close(dmabuf_fd);
+	if (heap_fd >= 0)
+		close(heap_fd);
+}
+
+
+int main(void)
+{
+	DIR *d;
+	struct dirent *dir;
+
+	d = opendir(DEVPATH);
+	if (!d) {
+		printf("No %s directory?\n", DEVPATH);
+		return -1;
+	}
+
+	while ((dir = readdir(d)) != NULL) {
+		if (!strncmp(dir->d_name, ".", 2))
+			continue;
+		if (!strncmp(dir->d_name, "..", 3))
+			continue;
+
+		do_test(dir->d_name);
+	}
+	closedir(d);
+
+	return 0;
+}
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 0/5] DMA-BUF Heaps (destaging ION)
  2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
                   ` (4 preceding siblings ...)
  2019-06-24 19:49   ` John Stultz
@ 2019-07-01 21:45 ` Laura Abbott
  2019-07-01 21:55   ` John Stultz
  5 siblings, 1 reply; 53+ messages in thread
From: Laura Abbott @ 2019-07-01 21:45 UTC (permalink / raw)
  To: John Stultz, lkml
  Cc: Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Andrew F . Davis,
	Christoph Hellwig, Chenbo Feng, Alistair Strachan, dri-devel

On 6/24/19 3:49 PM, John Stultz wrote:
> Here is another pass at the dma-buf heaps patchset Andrew and I
> have been working on which tries to destage a fair chunk of ION
> functionality.
> 

I've gotten bogged down with both work and personal tasks
so I haven't had a chance to look too closely but, once again,
I'm happy to see this continue to move forward.

> The patchset implements per-heap devices which can be opened
> directly and then an ioctl is used to allocate a dmabuf from the
> heap.
> 
> The interface is similar, but much simpler then IONs, only
> providing an ALLOC ioctl.
> 
> Also, I've provided relatively simple system and cma heaps.
> 
> I've booted and tested these patches with AOSP on the HiKey960
> using the kernel tree here:
>    https://git.linaro.org/people/john.stultz/android-dev.git/log/?h=dev/dma-buf-heap
> 
> And the userspace changes here:
>    https://android-review.googlesource.com/c/device/linaro/hikey/+/909436
> 
> Compared to ION, this patchset is missing the system-contig,
> carveout and chunk heaps, as I don't have a device that uses
> those, so I'm unable to do much useful validation there.
> Additionally we have no upstream users of chunk or carveout,
> and the system-contig has been deprecated in the common/andoid-*
> kernels, so this should be ok.
> 
> I've also removed the stats accounting for now, since any such
> accounting should be implemented by dma-buf core or the heaps
> themselves.
> 
> 
> New in v6:
> * Number of cleanups and error path fixes suggested by Brian Starkey,
>    many thanks for his close review and suggestions!
> 
> 
> Outstanding concerns:
> * Need to better understand various secure heap implementations.
>    Some concern that heap private flags will be needed, but its
>    also possible that dma-buf heaps can't solve everyone's needs,
>    in which case, a vendor's secure buffer driver can implement
>    their own dma-buf exporter. So I'm not too worried here.
> 

syzbot found a DoS with Ion which I ACKed a fix for.
https://lore.kernel.org/lkml/03763360-a7de-de87-eb90-ba7838143930@I-love.SAKURA.ne.jp/
This series doesn't have the page pooling so that particular bug may
not be applicable but given this is not the first time I've
seen Ion used as a DoS mechanism, it would be good to think about
putting in some basic checks.

Thanks,
Laura

> Thoughts and feedback would be greatly appreciated!
> 
> thanks
> -john
> 
> 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: dri-devel@lists.freedesktop.org
> 
> Andrew F. Davis (1):
>    dma-buf: Add dma-buf heaps framework
> 
> John Stultz (4):
>    dma-buf: heaps: Add heap helpers
>    dma-buf: heaps: Add system heap to dmabuf heaps
>    dma-buf: heaps: Add CMA heap to dmabuf heaps
>    kselftests: Add dma-heap test
> 
>   MAINTAINERS                                   |  18 ++
>   drivers/dma-buf/Kconfig                       |  10 +
>   drivers/dma-buf/Makefile                      |   2 +
>   drivers/dma-buf/dma-heap.c                    | 249 +++++++++++++++++
>   drivers/dma-buf/heaps/Kconfig                 |  14 +
>   drivers/dma-buf/heaps/Makefile                |   4 +
>   drivers/dma-buf/heaps/cma_heap.c              | 169 +++++++++++
>   drivers/dma-buf/heaps/heap-helpers.c          | 262 ++++++++++++++++++
>   drivers/dma-buf/heaps/heap-helpers.h          |  54 ++++
>   drivers/dma-buf/heaps/system_heap.c           | 121 ++++++++
>   include/linux/dma-heap.h                      |  59 ++++
>   include/uapi/linux/dma-heap.h                 |  55 ++++
>   tools/testing/selftests/dmabuf-heaps/Makefile |   9 +
>   .../selftests/dmabuf-heaps/dmabuf-heap.c      | 234 ++++++++++++++++
>   14 files changed, 1260 insertions(+)
>   create mode 100644 drivers/dma-buf/dma-heap.c
>   create mode 100644 drivers/dma-buf/heaps/Kconfig
>   create mode 100644 drivers/dma-buf/heaps/Makefile
>   create mode 100644 drivers/dma-buf/heaps/cma_heap.c
>   create mode 100644 drivers/dma-buf/heaps/heap-helpers.c
>   create mode 100644 drivers/dma-buf/heaps/heap-helpers.h
>   create mode 100644 drivers/dma-buf/heaps/system_heap.c
>   create mode 100644 include/linux/dma-heap.h
>   create mode 100644 include/uapi/linux/dma-heap.h
>   create mode 100644 tools/testing/selftests/dmabuf-heaps/Makefile
>   create mode 100644 tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
> 


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

* Re: [PATCH v6 0/5] DMA-BUF Heaps (destaging ION)
  2019-07-01 21:45 ` [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) Laura Abbott
@ 2019-07-01 21:55   ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-01 21:55 UTC (permalink / raw)
  To: Laura Abbott
  Cc: lkml, Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Andrew F . Davis,
	Christoph Hellwig, Chenbo Feng, Alistair Strachan, dri-devel

On Mon, Jul 1, 2019 at 2:45 PM Laura Abbott <labbott@redhat.com> wrote:
>
> On 6/24/19 3:49 PM, John Stultz wrote:
> > Here is another pass at the dma-buf heaps patchset Andrew and I
> > have been working on which tries to destage a fair chunk of ION
> > functionality.
> >
>
> I've gotten bogged down with both work and personal tasks
> so I haven't had a chance to look too closely but, once again,
> I'm happy to see this continue to move forward.
>
> > The patchset implements per-heap devices which can be opened
> > directly and then an ioctl is used to allocate a dmabuf from the
> > heap.
> >
> > The interface is similar, but much simpler then IONs, only
> > providing an ALLOC ioctl.
> >
> > Also, I've provided relatively simple system and cma heaps.
> >
> > I've booted and tested these patches with AOSP on the HiKey960
> > using the kernel tree here:
> >    https://git.linaro.org/people/john.stultz/android-dev.git/log/?h=dev/dma-buf-heap
> >
> > And the userspace changes here:
> >    https://android-review.googlesource.com/c/device/linaro/hikey/+/909436
> >
> > Compared to ION, this patchset is missing the system-contig,
> > carveout and chunk heaps, as I don't have a device that uses
> > those, so I'm unable to do much useful validation there.
> > Additionally we have no upstream users of chunk or carveout,
> > and the system-contig has been deprecated in the common/andoid-*
> > kernels, so this should be ok.
> >
> > I've also removed the stats accounting for now, since any such
> > accounting should be implemented by dma-buf core or the heaps
> > themselves.
> >
> >
> > New in v6:
> > * Number of cleanups and error path fixes suggested by Brian Starkey,
> >    many thanks for his close review and suggestions!
> >
> >
> > Outstanding concerns:
> > * Need to better understand various secure heap implementations.
> >    Some concern that heap private flags will be needed, but its
> >    also possible that dma-buf heaps can't solve everyone's needs,
> >    in which case, a vendor's secure buffer driver can implement
> >    their own dma-buf exporter. So I'm not too worried here.
> >
>
> syzbot found a DoS with Ion which I ACKed a fix for.
> https://lore.kernel.org/lkml/03763360-a7de-de87-eb90-ba7838143930@I-love.SAKURA.ne.jp/
> This series doesn't have the page pooling so that particular bug may
> not be applicable but given this is not the first time I've
> seen Ion used as a DoS mechanism, it would be good to think about
> putting in some basic checks.

Yea, there's no shrinker right now (and my WIP page pool
implementation steals the network core's pagepool, which is statically
sized).

But the check in the alloc code seems reasonable so I can add it to
what I have. Appreciate the suggestion!

thanks
-john

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-06-24 19:49   ` John Stultz
  (?)
@ 2019-07-18 10:06   ` Christoph Hellwig
  2019-07-23  4:09       ` John Stultz
  -1 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-18 10:06 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

> +void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
> +			     void (*free)(struct heap_helper_buffer *))

Please use a lower case naming following the naming scheme for the
rest of the file.

> +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;
> +}

Unless I'm misreading the patches this is used for the same pages that
also might be dma mapped.  In this case you need to use
flush_kernel_vmap_range and invalidate_kernel_vmap_range in the right
places to ensure coherency between the vmap and device view.  Please
also document the buffer ownership, as this really can get complicated.

> +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;
> +
> +	vmf->page = buffer->pages[vmf->pgoff];
> +	get_page(vmf->page);
> +
> +	return 0;
> +}

Is there any exlusion between mmap / vmap and the device accessing
the data?  Without that you are going to run into a lot of coherency
problems.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-06-24 19:49 ` [PATCH v6 4/5] dma-buf: heaps: Add CMA " John Stultz
@ 2019-07-18 10:08   ` Christoph Hellwig
  2019-07-23  5:04       ` John Stultz
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-18 10:08 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Christoph Hellwig, Chenbo Feng, Alistair Strachan,
	dri-devel

This and the previous one seem very much duplicated boilerplate
code.  Why can't just normal branches for allocating and freeing
normal pages vs cma?  We even have an existing helper for that
with dma_alloc_contiguous().

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-18 10:06   ` Christoph Hellwig
@ 2019-07-23  4:09       ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-23  4:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju, Rob Clark

On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> > +void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
> > +                          void (*free)(struct heap_helper_buffer *))
>
> Please use a lower case naming following the naming scheme for the
> rest of the file.

Yes! Apologies as this was a hold-over from when the initialization
function was an inline function in the style of
INIT_WORK/INIT_LIST_HEAD. No longer appropriate that its a function.
I'll change it.

> > +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;
> > +}
>
> Unless I'm misreading the patches this is used for the same pages that
> also might be dma mapped.  In this case you need to use
> flush_kernel_vmap_range and invalidate_kernel_vmap_range in the right
> places to ensure coherency between the vmap and device view.  Please
> also document the buffer ownership, as this really can get complicated.

Forgive me I wasn't familiar with those calls, but this seems like it
would apply to all dma-buf exporters if so, and I don't see any
similar flush_kernel_vmap_range calls there (both functions are
seemingly only used by xfs, md and bio).

We do have the dma_heap_dma_buf_begin_cpu_access()/dma_heap_dma_buf_end_cpu_access()
hooks (see more on these below) which sync the buffers for each
attachment (via dma_sync_sg_for_cpu/device), and are used around cpu
access to the buffers. Are you suggesting the
flush_kernel_vmap_range() call be added to those hooks or is the
dma_sync_sg_for_* calls sufficient there?

> > +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;
> > +
> > +     vmf->page = buffer->pages[vmf->pgoff];
> > +     get_page(vmf->page);
> > +
> > +     return 0;
> > +}
>
> Is there any exlusion between mmap / vmap and the device accessing
> the data?  Without that you are going to run into a lot of coherency
> problems.

This has actually been a concern of mine recently, but at the higher
dma-buf core level.  Conceptually, there is the
dma_buf_map_attachment() and dma_buf_unmap_attachment() calls drivers
use to map the buffer to an attached device, and there are the
dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() calls which
are to be done when touching the cpu mapped pages.  These look like
serializing functions, but actually don't seem to have any enforcement
mechanism to exclude parallel access.

To me it seems like adding the exclusion between those operations
should be done at the dmabuf core level, and would actually be helpful
for optimizing some of the cache maintenance rules w/ dmabuf.  Does
this sound like something closer to what your suggesting, or am I
misunderstanding your point?

Again, I really appreciate the review and feedback!

Thanks so much!
-john

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-23  4:09       ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-23  4:09 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Vincent Donnefort,
	Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Alistair Strachan,
	Xiaqing (A),
	Andrew F . Davis, Hridya Valsaraju, Pratik Patel, butao

On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> > +void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
> > +                          void (*free)(struct heap_helper_buffer *))
>
> Please use a lower case naming following the naming scheme for the
> rest of the file.

Yes! Apologies as this was a hold-over from when the initialization
function was an inline function in the style of
INIT_WORK/INIT_LIST_HEAD. No longer appropriate that its a function.
I'll change it.

> > +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;
> > +}
>
> Unless I'm misreading the patches this is used for the same pages that
> also might be dma mapped.  In this case you need to use
> flush_kernel_vmap_range and invalidate_kernel_vmap_range in the right
> places to ensure coherency between the vmap and device view.  Please
> also document the buffer ownership, as this really can get complicated.

Forgive me I wasn't familiar with those calls, but this seems like it
would apply to all dma-buf exporters if so, and I don't see any
similar flush_kernel_vmap_range calls there (both functions are
seemingly only used by xfs, md and bio).

We do have the dma_heap_dma_buf_begin_cpu_access()/dma_heap_dma_buf_end_cpu_access()
hooks (see more on these below) which sync the buffers for each
attachment (via dma_sync_sg_for_cpu/device), and are used around cpu
access to the buffers. Are you suggesting the
flush_kernel_vmap_range() call be added to those hooks or is the
dma_sync_sg_for_* calls sufficient there?

> > +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;
> > +
> > +     vmf->page = buffer->pages[vmf->pgoff];
> > +     get_page(vmf->page);
> > +
> > +     return 0;
> > +}
>
> Is there any exlusion between mmap / vmap and the device accessing
> the data?  Without that you are going to run into a lot of coherency
> problems.

This has actually been a concern of mine recently, but at the higher
dma-buf core level.  Conceptually, there is the
dma_buf_map_attachment() and dma_buf_unmap_attachment() calls drivers
use to map the buffer to an attached device, and there are the
dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() calls which
are to be done when touching the cpu mapped pages.  These look like
serializing functions, but actually don't seem to have any enforcement
mechanism to exclude parallel access.

To me it seems like adding the exclusion between those operations
should be done at the dmabuf core level, and would actually be helpful
for optimizing some of the cache maintenance rules w/ dmabuf.  Does
this sound like something closer to what your suggesting, or am I
misunderstanding your point?

Again, I really appreciate the review and feedback!

Thanks so much!
-john
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-18 10:08   ` Christoph Hellwig
@ 2019-07-23  5:04       ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-23  5:04 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 18, 2019 at 3:08 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> This and the previous one seem very much duplicated boilerplate
> code.

So yes, there is some duplicate boilerplate between the system and cma
heaps particularly in the allocation function, where we allocate and
set up the helper buffer structure, allocate the pages, then create
and export the dmabuf. I took a pass at trying to minimize some of
this earlier, but those efforts ended up adding helper functions that
take a ton of arguments, and had some trouble properly handling error
paths without leaking memory, so I left it as is.

I'll try to take another pass myself but if you have specific
suggestions for improving here, I'd be happy to try them.

> Why can't just normal branches for allocating and freeing
> normal pages vs cma?  We even have an existing helper for that
> with dma_alloc_contiguous().

Apologies, I'm not sure I'm understanding your suggestion here.
dma_alloc_contiguous() does have some interesting optimizations
(avoiding allocating single page from cma), though its focus on
default area vs specific device area doesn't quite match up the usage
model for dma heaps.  Instead of allocating memory for a single
device, we want to be able to allow userland, for a given usage mode,
to be able to allocate a dmabuf from a specific heap of memory which
will satisfy the usage mode for that buffer pipeline (across multiple
devices).

Now, indeed, the system and cma heaps in this patchset are a bit
simple/trivial (though useful with my devices that require contiguous
buffers for the display driver), but more complex ION heaps have
traditionally stayed out of tree in vendor code, in many cases making
incompatible tweaks to the ION core dmabuf exporter logic. That's why
dmabuf heaps is trying to destage ION in a way that allows heaps to
implement their exporter logic themselves, so we can start pulling
those more complicated heaps out of their vendor hidey-holes and get
some proper upstream review.

But I suspect I just am confused as to what your suggesting. Maybe
could you expand a bit? Apologies for being a bit dense.

Thanks again for the input!
-john

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
@ 2019-07-23  5:04       ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-23  5:04 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Vincent Donnefort,
	Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Alistair Strachan,
	Xiaqing (A),
	Andrew F . Davis, Pratik Patel, butao

On Thu, Jul 18, 2019 at 3:08 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> This and the previous one seem very much duplicated boilerplate
> code.

So yes, there is some duplicate boilerplate between the system and cma
heaps particularly in the allocation function, where we allocate and
set up the helper buffer structure, allocate the pages, then create
and export the dmabuf. I took a pass at trying to minimize some of
this earlier, but those efforts ended up adding helper functions that
take a ton of arguments, and had some trouble properly handling error
paths without leaking memory, so I left it as is.

I'll try to take another pass myself but if you have specific
suggestions for improving here, I'd be happy to try them.

> Why can't just normal branches for allocating and freeing
> normal pages vs cma?  We even have an existing helper for that
> with dma_alloc_contiguous().

Apologies, I'm not sure I'm understanding your suggestion here.
dma_alloc_contiguous() does have some interesting optimizations
(avoiding allocating single page from cma), though its focus on
default area vs specific device area doesn't quite match up the usage
model for dma heaps.  Instead of allocating memory for a single
device, we want to be able to allow userland, for a given usage mode,
to be able to allocate a dmabuf from a specific heap of memory which
will satisfy the usage mode for that buffer pipeline (across multiple
devices).

Now, indeed, the system and cma heaps in this patchset are a bit
simple/trivial (though useful with my devices that require contiguous
buffers for the display driver), but more complex ION heaps have
traditionally stayed out of tree in vendor code, in many cases making
incompatible tweaks to the ION core dmabuf exporter logic. That's why
dmabuf heaps is trying to destage ION in a way that allows heaps to
implement their exporter logic themselves, so we can start pulling
those more complicated heaps out of their vendor hidey-holes and get
some proper upstream review.

But I suspect I just am confused as to what your suggesting. Maybe
could you expand a bit? Apologies for being a bit dense.

Thanks again for the input!
-john
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-23  4:09       ` John Stultz
@ 2019-07-23 20:09         ` Rob Clark
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Clark @ 2019-07-23 20:09 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju

On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
>
> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> >
> > Is there any exlusion between mmap / vmap and the device accessing
> > the data?  Without that you are going to run into a lot of coherency
> > problems.

dma_fence is basically the way to handle exclusion between different
device access (since device access tends to be asynchronous).  For
device<->device access, each driver is expected to take care of any
cache(s) that the device might have.  (Ie. device writing to buffer
should flush it's caches if needed before signalling fence to let
reading device know that it is safe to read, etc.)

_begin/end_cpu_access() is intended to be the exclusion for CPU access
(which is synchronous)

BR,
-R

> This has actually been a concern of mine recently, but at the higher
> dma-buf core level.  Conceptually, there is the
> dma_buf_map_attachment() and dma_buf_unmap_attachment() calls drivers
> use to map the buffer to an attached device, and there are the
> dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() calls which
> are to be done when touching the cpu mapped pages.  These look like
> serializing functions, but actually don't seem to have any enforcement
> mechanism to exclude parallel access.
>
> To me it seems like adding the exclusion between those operations
> should be done at the dmabuf core level, and would actually be helpful
> for optimizing some of the cache maintenance rules w/ dmabuf.  Does
> this sound like something closer to what your suggesting, or am I
> misunderstanding your point?
>
> Again, I really appreciate the review and feedback!
>
> Thanks so much!
> -john

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-23 20:09         ` Rob Clark
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Clark @ 2019-07-23 20:09 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel, Hri

On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
>
> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> >
> > Is there any exlusion between mmap / vmap and the device accessing
> > the data?  Without that you are going to run into a lot of coherency
> > problems.

dma_fence is basically the way to handle exclusion between different
device access (since device access tends to be asynchronous).  For
device<->device access, each driver is expected to take care of any
cache(s) that the device might have.  (Ie. device writing to buffer
should flush it's caches if needed before signalling fence to let
reading device know that it is safe to read, etc.)

_begin/end_cpu_access() is intended to be the exclusion for CPU access
(which is synchronous)

BR,
-R

> This has actually been a concern of mine recently, but at the higher
> dma-buf core level.  Conceptually, there is the
> dma_buf_map_attachment() and dma_buf_unmap_attachment() calls drivers
> use to map the buffer to an attached device, and there are the
> dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() calls which
> are to be done when touching the cpu mapped pages.  These look like
> serializing functions, but actually don't seem to have any enforcement
> mechanism to exclude parallel access.
>
> To me it seems like adding the exclusion between those operations
> should be done at the dmabuf core level, and would actually be helpful
> for optimizing some of the cache maintenance rules w/ dmabuf.  Does
> this sound like something closer to what your suggesting, or am I
> misunderstanding your point?
>
> Again, I really appreciate the review and feedback!
>
> Thanks so much!
> -john

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-23 20:09         ` Rob Clark
@ 2019-07-24  6:55           ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-24  6:55 UTC (permalink / raw)
  To: Rob Clark
  Cc: John Stultz, Christoph Hellwig, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Andrew F . Davis,
	Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju

On Tue, Jul 23, 2019 at 01:09:55PM -0700, Rob Clark wrote:
> On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
> >
> > On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> > >
> > > Is there any exlusion between mmap / vmap and the device accessing
> > > the data?  Without that you are going to run into a lot of coherency
> > > problems.
> 
> dma_fence is basically the way to handle exclusion between different
> device access (since device access tends to be asynchronous).  For
> device<->device access, each driver is expected to take care of any
> cache(s) that the device might have.  (Ie. device writing to buffer
> should flush it's caches if needed before signalling fence to let
> reading device know that it is safe to read, etc.)
> 
> _begin/end_cpu_access() is intended to be the exclusion for CPU access
> (which is synchronous)

What I mean is that we need a clear state machine (preferably including
ownership tracking ala dma-debug) where a piece of memory has one
owner at a time that can access it.  Only the owner can access is at
that time, and at any owner switch we need to flush/invalidate all
relevant caches.  And with memory that is vmaped and mapped to userspace
that can get really complicated.

The above sounds like you have some of that in place, but we'll really
need clear rules to make sure we don't have holes in the scheme.

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-24  6:55           ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-24  6:55 UTC (permalink / raw)
  To: Rob Clark
  Cc: John Stultz, Christoph Hellwig, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Andrew F . Davis,
	Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Tue, Jul 23, 2019 at 01:09:55PM -0700, Rob Clark wrote:
> On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
> >
> > On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> > >
> > > Is there any exlusion between mmap / vmap and the device accessing
> > > the data?  Without that you are going to run into a lot of coherency
> > > problems.
> 
> dma_fence is basically the way to handle exclusion between different
> device access (since device access tends to be asynchronous).  For
> device<->device access, each driver is expected to take care of any
> cache(s) that the device might have.  (Ie. device writing to buffer
> should flush it's caches if needed before signalling fence to let
> reading device know that it is safe to read, etc.)
> 
> _begin/end_cpu_access() is intended to be the exclusion for CPU access
> (which is synchronous)

What I mean is that we need a clear state machine (preferably including
ownership tracking ala dma-debug) where a piece of memory has one
owner at a time that can access it.  Only the owner can access is at
that time, and at any owner switch we need to flush/invalidate all
relevant caches.  And with memory that is vmaped and mapped to userspace
that can get really complicated.

The above sounds like you have some of that in place, but we'll really
need clear rules to make sure we don't have holes in the scheme.

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-23  4:09       ` John Stultz
@ 2019-07-24  6:58         ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-24  6:58 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju, Rob Clark

On Mon, Jul 22, 2019 at 09:09:25PM -0700, John Stultz wrote:
> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> >
> > > +void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
> > > +                          void (*free)(struct heap_helper_buffer *))
> >
> > Please use a lower case naming following the naming scheme for the
> > rest of the file.
> 
> Yes! Apologies as this was a hold-over from when the initialization
> function was an inline function in the style of
> INIT_WORK/INIT_LIST_HEAD. No longer appropriate that its a function.
> I'll change it.
> 
> > > +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;
> > > +}
> >
> > Unless I'm misreading the patches this is used for the same pages that
> > also might be dma mapped.  In this case you need to use
> > flush_kernel_vmap_range and invalidate_kernel_vmap_range in the right
> > places to ensure coherency between the vmap and device view.  Please
> > also document the buffer ownership, as this really can get complicated.
> 
> Forgive me I wasn't familiar with those calls, but this seems like it
> would apply to all dma-buf exporters if so, and I don't see any
> similar flush_kernel_vmap_range calls there (both functions are
> seemingly only used by xfs, md and bio).
> 
> We do have the dma_heap_dma_buf_begin_cpu_access()/dma_heap_dma_buf_end_cpu_access()
> hooks (see more on these below) which sync the buffers for each
> attachment (via dma_sync_sg_for_cpu/device), and are used around cpu
> access to the buffers. Are you suggesting the
> flush_kernel_vmap_range() call be added to those hooks or is the
> dma_sync_sg_for_* calls sufficient there?

dma_sync_sg_for_* only operates on the kernel direct mapping, that
is what you get from page_address/kmap* for the page.  But with vmap
your create another alias in kernel virtual space, which
dma_sync_sg_for_* can't know about.  Now for most CPUs caches are
indexed by physical addresses so this doesn't matter, but a significant
minority of CPUs (parisc, some arm, some mips) index by virtual address,
in which case we need non-empy flush_kernel_vmap_range and
invalidate_kernel_vmap_range helper to deal with that vmap alias.

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-24  6:58         ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-24  6:58 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel, Hri

On Mon, Jul 22, 2019 at 09:09:25PM -0700, John Stultz wrote:
> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
> >
> > > +void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer,
> > > +                          void (*free)(struct heap_helper_buffer *))
> >
> > Please use a lower case naming following the naming scheme for the
> > rest of the file.
> 
> Yes! Apologies as this was a hold-over from when the initialization
> function was an inline function in the style of
> INIT_WORK/INIT_LIST_HEAD. No longer appropriate that its a function.
> I'll change it.
> 
> > > +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;
> > > +}
> >
> > Unless I'm misreading the patches this is used for the same pages that
> > also might be dma mapped.  In this case you need to use
> > flush_kernel_vmap_range and invalidate_kernel_vmap_range in the right
> > places to ensure coherency between the vmap and device view.  Please
> > also document the buffer ownership, as this really can get complicated.
> 
> Forgive me I wasn't familiar with those calls, but this seems like it
> would apply to all dma-buf exporters if so, and I don't see any
> similar flush_kernel_vmap_range calls there (both functions are
> seemingly only used by xfs, md and bio).
> 
> We do have the dma_heap_dma_buf_begin_cpu_access()/dma_heap_dma_buf_end_cpu_access()
> hooks (see more on these below) which sync the buffers for each
> attachment (via dma_sync_sg_for_cpu/device), and are used around cpu
> access to the buffers. Are you suggesting the
> flush_kernel_vmap_range() call be added to those hooks or is the
> dma_sync_sg_for_* calls sufficient there?

dma_sync_sg_for_* only operates on the kernel direct mapping, that
is what you get from page_address/kmap* for the page.  But with vmap
your create another alias in kernel virtual space, which
dma_sync_sg_for_* can't know about.  Now for most CPUs caches are
indexed by physical addresses so this doesn't matter, but a significant
minority of CPUs (parisc, some arm, some mips) index by virtual address,
in which case we need non-empy flush_kernel_vmap_range and
invalidate_kernel_vmap_range helper to deal with that vmap alias.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-23  5:04       ` John Stultz
  (?)
@ 2019-07-24  6:59       ` Christoph Hellwig
  2019-07-24  8:08         ` Benjamin Gaignard
                           ` (3 more replies)
  -1 siblings, 4 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-24  6:59 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
> Apologies, I'm not sure I'm understanding your suggestion here.
> dma_alloc_contiguous() does have some interesting optimizations
> (avoiding allocating single page from cma), though its focus on
> default area vs specific device area doesn't quite match up the usage
> model for dma heaps.  Instead of allocating memory for a single
> device, we want to be able to allow userland, for a given usage mode,
> to be able to allocate a dmabuf from a specific heap of memory which
> will satisfy the usage mode for that buffer pipeline (across multiple
> devices).
> 
> Now, indeed, the system and cma heaps in this patchset are a bit
> simple/trivial (though useful with my devices that require contiguous
> buffers for the display driver), but more complex ION heaps have
> traditionally stayed out of tree in vendor code, in many cases making
> incompatible tweaks to the ION core dmabuf exporter logic.

So what would the more complicated heaps be?

> That's why
> dmabuf heaps is trying to destage ION in a way that allows heaps to
> implement their exporter logic themselves, so we can start pulling
> those more complicated heaps out of their vendor hidey-holes and get
> some proper upstream review.
> 
> But I suspect I just am confused as to what your suggesting. Maybe
> could you expand a bit? Apologies for being a bit dense.

My suggestion is to merge the system and CMA heaps.  CMA (at least
the system-wide CMA area) is really just an optimization to get
large contigous regions more easily.  We should make use of it as
transparent as possible, just like we do in the DMA code.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24  6:59       ` Christoph Hellwig
@ 2019-07-24  8:08         ` Benjamin Gaignard
  2019-07-25 12:45           ` Christoph Hellwig
  2019-07-24 11:38         ` Laura Abbott
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 53+ messages in thread
From: Benjamin Gaignard @ 2019-07-24  8:08 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

Le mer. 24 juil. 2019 à 09:00, Christoph Hellwig <hch@infradead.org> a écrit :
>
> On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
> > Apologies, I'm not sure I'm understanding your suggestion here.
> > dma_alloc_contiguous() does have some interesting optimizations
> > (avoiding allocating single page from cma), though its focus on
> > default area vs specific device area doesn't quite match up the usage
> > model for dma heaps.  Instead of allocating memory for a single
> > device, we want to be able to allow userland, for a given usage mode,
> > to be able to allocate a dmabuf from a specific heap of memory which
> > will satisfy the usage mode for that buffer pipeline (across multiple
> > devices).
> >
> > Now, indeed, the system and cma heaps in this patchset are a bit
> > simple/trivial (though useful with my devices that require contiguous
> > buffers for the display driver), but more complex ION heaps have
> > traditionally stayed out of tree in vendor code, in many cases making
> > incompatible tweaks to the ION core dmabuf exporter logic.
>
> So what would the more complicated heaps be?
>
> > That's why
> > dmabuf heaps is trying to destage ION in a way that allows heaps to
> > implement their exporter logic themselves, so we can start pulling
> > those more complicated heaps out of their vendor hidey-holes and get
> > some proper upstream review.
> >
> > But I suspect I just am confused as to what your suggesting. Maybe
> > could you expand a bit? Apologies for being a bit dense.
>
> My suggestion is to merge the system and CMA heaps.  CMA (at least
> the system-wide CMA area) is really just an optimization to get
> large contigous regions more easily.  We should make use of it as
> transparent as possible, just like we do in the DMA code.

CMA has made possible to get large regions of memories and to give some
priority on device allocating pages on it. I don't think that possible
with system
heap so I suggest to keep CMA heap if we want to be able to port a maximum
of applications on dma-buf-heap.

Benjamin

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24  6:59       ` Christoph Hellwig
  2019-07-24  8:08         ` Benjamin Gaignard
@ 2019-07-24 11:38         ` Laura Abbott
  2019-07-25 12:48           ` Christoph Hellwig
  2019-07-24 15:46         ` Andrew F. Davis
  2019-07-24 18:46           ` John Stultz
  3 siblings, 1 reply; 53+ messages in thread
From: Laura Abbott @ 2019-07-24 11:38 UTC (permalink / raw)
  To: Christoph Hellwig, John Stultz
  Cc: lkml, Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Andrew F . Davis,
	Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/24/19 2:59 AM, Christoph Hellwig wrote:
> On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
>> Apologies, I'm not sure I'm understanding your suggestion here.
>> dma_alloc_contiguous() does have some interesting optimizations
>> (avoiding allocating single page from cma), though its focus on
>> default area vs specific device area doesn't quite match up the usage
>> model for dma heaps.  Instead of allocating memory for a single
>> device, we want to be able to allow userland, for a given usage mode,
>> to be able to allocate a dmabuf from a specific heap of memory which
>> will satisfy the usage mode for that buffer pipeline (across multiple
>> devices).
>>
>> Now, indeed, the system and cma heaps in this patchset are a bit
>> simple/trivial (though useful with my devices that require contiguous
>> buffers for the display driver), but more complex ION heaps have
>> traditionally stayed out of tree in vendor code, in many cases making
>> incompatible tweaks to the ION core dmabuf exporter logic.
> 
> So what would the more complicated heaps be?
> 
>> That's why
>> dmabuf heaps is trying to destage ION in a way that allows heaps to
>> implement their exporter logic themselves, so we can start pulling
>> those more complicated heaps out of their vendor hidey-holes and get
>> some proper upstream review.
>>
>> But I suspect I just am confused as to what your suggesting. Maybe
>> could you expand a bit? Apologies for being a bit dense.
> 
> My suggestion is to merge the system and CMA heaps.  CMA (at least
> the system-wide CMA area) is really just an optimization to get
> large contigous regions more easily.  We should make use of it as
> transparent as possible, just like we do in the DMA code.
> 

It's not just an optimization for Ion though. Ion was designed to
let the callers choose between system and multiple CMA heaps. On other
systems there may be multiple CMA regions dedicated to a specific
purpose or placed at a specific address. The callers need to
be able to choose exactly whether they want a particular CMA region
or discontiguous regions.

Thanks,
Laura

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-24  6:55           ` Christoph Hellwig
@ 2019-07-24 15:20             ` Andrew F. Davis
  -1 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-24 15:20 UTC (permalink / raw)
  To: Christoph Hellwig, Rob Clark
  Cc: John Stultz, lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju

On 7/24/19 2:55 AM, Christoph Hellwig wrote:
> On Tue, Jul 23, 2019 at 01:09:55PM -0700, Rob Clark wrote:
>> On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
>>>
>>> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
>>>>
>>>> Is there any exlusion between mmap / vmap and the device accessing
>>>> the data?  Without that you are going to run into a lot of coherency
>>>> problems.
>>
>> dma_fence is basically the way to handle exclusion between different
>> device access (since device access tends to be asynchronous).  For
>> device<->device access, each driver is expected to take care of any
>> cache(s) that the device might have.  (Ie. device writing to buffer
>> should flush it's caches if needed before signalling fence to let
>> reading device know that it is safe to read, etc.)
>>
>> _begin/end_cpu_access() is intended to be the exclusion for CPU access
>> (which is synchronous)
> 
> What I mean is that we need a clear state machine (preferably including
> ownership tracking ala dma-debug) where a piece of memory has one
> owner at a time that can access it.  Only the owner can access is at
> that time, and at any owner switch we need to flush/invalidate all
> relevant caches.  And with memory that is vmaped and mapped to userspace
> that can get really complicated.
> 
> The above sounds like you have some of that in place, but we'll really
> need clear rules to make sure we don't have holes in the scheme.
> 

Well then lets think on this. A given buffer can have 3 owners states
(CPU-owned, Device-owned, and Un-owned). These are based on the caching
state from the CPU perspective.

If a buffer is CPU-owned then we (Linux) can write to the buffer safely
without worry that the data is stale or that it will be accessed by the
device without having been flushed. Device-owned buffers should not be
accessed by the CPU, and inter-device synchronization should be handled
by fencing as Rob points out. Un-owned is how a buffer starts for
consistency and to prevent unneeded cache operations on unwritten buffers.

We also need to track the mapping states, 4 states for this, CPU-mapped,
Device-mapped, CPU/Device-mapped, unmapped. Should be self explanatory,
map_dma_buf maps towards the device, mmap/vmap/kmap towards the CPU.
Leaving a buffer mapped by the CPU while device access takes place is
safe as long as ownership is taken before any access. One more point, we
assume reference counting for the below discussion, for instance
unmap_dma_buf refers to the last device unmapping, map_dma_buf refers
only to the first.

This gives 12 combined states, if we assume a buffer will always be
owned when it has someone mapping it, either CPU or device or both, then
we can drop 3 states. If a buffer is only mapped into one space, then
that space owns it, this drops 2 cross-owned states. Lastly if not
mapped by either space then the buffer becomes un-owned (and the backing
memory can be freed or migrated as needed). Leaving us 5 valid states.

* Un-Owned Un-Mapped
* Device-Owned Device-Mapped
* Device-Owned CPU/Device-Mapped
* CPU-Owned CPU-Mapped
* CPU-Owned CPU/Device-Mapped

There are 6 DMA-BUF operations (classes) on a buffer:

* map_dma_buf
* unmap_dma_buf
* begin_cpu_access
* end_cpu_access
* mmap/vmap/kmap
* ummanp/vunmap/kunmap

From all this I've suggest the following state-machine(in DOT language):

Note: Buffers start in "Un-Owned Un-Mapped" and can only be freed from
that state.

Note: Commented out states/transitions are not valid but here to prove
completeness

-------------------------------------------------------------------

digraph dma_buf_buffer_states
{
	label = "DMA-BUF Buffer states";

	uo_um [ label="Un-Owned\nUn-Mapped" ];
//	uo_dm [ label="Un-Owned\nDevice-Mapped" ];
//	uo_cm [ label="Un-Owned\nCPU-Mapped" ];
//	uo_cdm [ label="Un-Owned\nCPU/Device-Mapped" ];

//	do_um [ label="Device-Owned\nUn-Mapped" ];
	do_dm [ label="Device-Owned\nDevice-Mapped" ];
//	do_cm [ label="Device-Owned\nCPU-Mapped" ];
	do_cdm [ label="Device-Owned\nCPU/Device-Mapped" ];

//	co_um [ label="CPU-Owned\nUn-Mapped" ];
//	co_dm [ label="CPU-Owned\nDevice-Mapped" ];
	co_cm [ label="CPU-Owned\nCPU-Mapped" ];
	co_cdm [ label="CPU-Owned\nCPU/Device-Mapped" ];

	/* From Un-Owned Un-Mapped */
		uo_um -> do_dm		[ label="map_dma_buf" ];
//		uo_um ->		[ label="unmap_dma_buf" ];
//		uo_um -> 		[ label="begin_cpu_access" ];
//		uo_um ->		[ label="end_cpu_access" ];
		uo_um -> co_cm		[ label="mmap/vmap/kmap" ];
//		uo_um -> 		[ label="ummanp/vunmap/kunmap" ];

	/* From Device-Owned Device-Mapped */
		do_dm -> do_dm		[ label="map_dma_buf" ];
		do_dm -> uo_um		[ label="unmap_dma_buf" ];
//		do_dm -> 		[ label="begin_cpu_access" ];
//		do_dm ->		[ label="end_cpu_access" ];
		do_dm -> do_cdm		[ label="mmap/vmap/kmap" ];
//		do_dm -> 		[ label="ummanp/vunmap/kunmap" ];

	/* From Device-Owned CPU/Device-Mapped */
		do_cdm -> do_cdm	[ label="map_dma_buf" ];
		do_cdm -> co_cm		[ label="unmap_dma_buf" ];
		do_cdm -> co_cdm	[ label="begin_cpu_access" ];
//		do_cdm ->		[ label="end_cpu_access" ];
		do_cdm -> do_cdm	[ label="mmap/vmap/kmap" ];
		do_cdm -> do_dm		[ label="ummanp/vunmap/kunmap" ];

	/* From CPU-Owned CPU-Mapped */
		co_cm -> co_cdm		[ label="map_dma_buf" ];
//		co_cm -> 		[ label="unmap_dma_buf" ];
//		co_cm -> 		[ label="begin_cpu_access" ];
		co_cm -> co_cm		[ label="end_cpu_access" ];
//		co_cm ->		[ label="mmap/vmap/kmap" ];
		co_cm -> uo_um		[ label="ummanp/vunmap/kunmap" ];

	/* From CPU-Owned CPU/Device-Mapped */
		co_cdm -> co_cdm	[ label="map_dma_buf" ];
		co_cdm -> co_cm		[ label="unmap_dma_buf" ];
//		co_cdm -> 		[ label="begin_cpu_access" ];
		co_cdm -> do_cdm	[ label="end_cpu_access" ];
		co_cdm -> co_cdm	[ label="mmap/vmap/kmap" ];
//		co_cdm ->		[ label="ummanp/vunmap/kunmap" ];

	{
		rank = same;
		co_cm -> do_dm [ style=invis ];
		rankdir = LR;
	}

	{
		rank = same;
		co_cdm -> do_cdm [ style=invis ];
		rankdir = LR;
	}
}

-------------------------------------------------------------------

If we consider this the "official" model, then we can start optimizing
cache operations, and start forbidding some nonsensical operations.

What do y'all think?

Andrew

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-24 15:20             ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-24 15:20 UTC (permalink / raw)
  To: Christoph Hellwig, Rob Clark
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Alistair Strachan,
	Vincent Donnefort, Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Xiaqing (A),
	Hridya Valsaraju, Pratik Patel, butao

On 7/24/19 2:55 AM, Christoph Hellwig wrote:
> On Tue, Jul 23, 2019 at 01:09:55PM -0700, Rob Clark wrote:
>> On Mon, Jul 22, 2019 at 9:09 PM John Stultz <john.stultz@linaro.org> wrote:
>>>
>>> On Thu, Jul 18, 2019 at 3:06 AM Christoph Hellwig <hch@infradead.org> wrote:
>>>>
>>>> Is there any exlusion between mmap / vmap and the device accessing
>>>> the data?  Without that you are going to run into a lot of coherency
>>>> problems.
>>
>> dma_fence is basically the way to handle exclusion between different
>> device access (since device access tends to be asynchronous).  For
>> device<->device access, each driver is expected to take care of any
>> cache(s) that the device might have.  (Ie. device writing to buffer
>> should flush it's caches if needed before signalling fence to let
>> reading device know that it is safe to read, etc.)
>>
>> _begin/end_cpu_access() is intended to be the exclusion for CPU access
>> (which is synchronous)
> 
> What I mean is that we need a clear state machine (preferably including
> ownership tracking ala dma-debug) where a piece of memory has one
> owner at a time that can access it.  Only the owner can access is at
> that time, and at any owner switch we need to flush/invalidate all
> relevant caches.  And with memory that is vmaped and mapped to userspace
> that can get really complicated.
> 
> The above sounds like you have some of that in place, but we'll really
> need clear rules to make sure we don't have holes in the scheme.
> 

Well then lets think on this. A given buffer can have 3 owners states
(CPU-owned, Device-owned, and Un-owned). These are based on the caching
state from the CPU perspective.

If a buffer is CPU-owned then we (Linux) can write to the buffer safely
without worry that the data is stale or that it will be accessed by the
device without having been flushed. Device-owned buffers should not be
accessed by the CPU, and inter-device synchronization should be handled
by fencing as Rob points out. Un-owned is how a buffer starts for
consistency and to prevent unneeded cache operations on unwritten buffers.

We also need to track the mapping states, 4 states for this, CPU-mapped,
Device-mapped, CPU/Device-mapped, unmapped. Should be self explanatory,
map_dma_buf maps towards the device, mmap/vmap/kmap towards the CPU.
Leaving a buffer mapped by the CPU while device access takes place is
safe as long as ownership is taken before any access. One more point, we
assume reference counting for the below discussion, for instance
unmap_dma_buf refers to the last device unmapping, map_dma_buf refers
only to the first.

This gives 12 combined states, if we assume a buffer will always be
owned when it has someone mapping it, either CPU or device or both, then
we can drop 3 states. If a buffer is only mapped into one space, then
that space owns it, this drops 2 cross-owned states. Lastly if not
mapped by either space then the buffer becomes un-owned (and the backing
memory can be freed or migrated as needed). Leaving us 5 valid states.

* Un-Owned Un-Mapped
* Device-Owned Device-Mapped
* Device-Owned CPU/Device-Mapped
* CPU-Owned CPU-Mapped
* CPU-Owned CPU/Device-Mapped

There are 6 DMA-BUF operations (classes) on a buffer:

* map_dma_buf
* unmap_dma_buf
* begin_cpu_access
* end_cpu_access
* mmap/vmap/kmap
* ummanp/vunmap/kunmap

From all this I've suggest the following state-machine(in DOT language):

Note: Buffers start in "Un-Owned Un-Mapped" and can only be freed from
that state.

Note: Commented out states/transitions are not valid but here to prove
completeness

-------------------------------------------------------------------

digraph dma_buf_buffer_states
{
	label = "DMA-BUF Buffer states";

	uo_um [ label="Un-Owned\nUn-Mapped" ];
//	uo_dm [ label="Un-Owned\nDevice-Mapped" ];
//	uo_cm [ label="Un-Owned\nCPU-Mapped" ];
//	uo_cdm [ label="Un-Owned\nCPU/Device-Mapped" ];

//	do_um [ label="Device-Owned\nUn-Mapped" ];
	do_dm [ label="Device-Owned\nDevice-Mapped" ];
//	do_cm [ label="Device-Owned\nCPU-Mapped" ];
	do_cdm [ label="Device-Owned\nCPU/Device-Mapped" ];

//	co_um [ label="CPU-Owned\nUn-Mapped" ];
//	co_dm [ label="CPU-Owned\nDevice-Mapped" ];
	co_cm [ label="CPU-Owned\nCPU-Mapped" ];
	co_cdm [ label="CPU-Owned\nCPU/Device-Mapped" ];

	/* From Un-Owned Un-Mapped */
		uo_um -> do_dm		[ label="map_dma_buf" ];
//		uo_um ->		[ label="unmap_dma_buf" ];
//		uo_um -> 		[ label="begin_cpu_access" ];
//		uo_um ->		[ label="end_cpu_access" ];
		uo_um -> co_cm		[ label="mmap/vmap/kmap" ];
//		uo_um -> 		[ label="ummanp/vunmap/kunmap" ];

	/* From Device-Owned Device-Mapped */
		do_dm -> do_dm		[ label="map_dma_buf" ];
		do_dm -> uo_um		[ label="unmap_dma_buf" ];
//		do_dm -> 		[ label="begin_cpu_access" ];
//		do_dm ->		[ label="end_cpu_access" ];
		do_dm -> do_cdm		[ label="mmap/vmap/kmap" ];
//		do_dm -> 		[ label="ummanp/vunmap/kunmap" ];

	/* From Device-Owned CPU/Device-Mapped */
		do_cdm -> do_cdm	[ label="map_dma_buf" ];
		do_cdm -> co_cm		[ label="unmap_dma_buf" ];
		do_cdm -> co_cdm	[ label="begin_cpu_access" ];
//		do_cdm ->		[ label="end_cpu_access" ];
		do_cdm -> do_cdm	[ label="mmap/vmap/kmap" ];
		do_cdm -> do_dm		[ label="ummanp/vunmap/kunmap" ];

	/* From CPU-Owned CPU-Mapped */
		co_cm -> co_cdm		[ label="map_dma_buf" ];
//		co_cm -> 		[ label="unmap_dma_buf" ];
//		co_cm -> 		[ label="begin_cpu_access" ];
		co_cm -> co_cm		[ label="end_cpu_access" ];
//		co_cm ->		[ label="mmap/vmap/kmap" ];
		co_cm -> uo_um		[ label="ummanp/vunmap/kunmap" ];

	/* From CPU-Owned CPU/Device-Mapped */
		co_cdm -> co_cdm	[ label="map_dma_buf" ];
		co_cdm -> co_cm		[ label="unmap_dma_buf" ];
//		co_cdm -> 		[ label="begin_cpu_access" ];
		co_cdm -> do_cdm	[ label="end_cpu_access" ];
		co_cdm -> co_cdm	[ label="mmap/vmap/kmap" ];
//		co_cdm ->		[ label="ummanp/vunmap/kunmap" ];

	{
		rank = same;
		co_cm -> do_dm [ style=invis ];
		rankdir = LR;
	}

	{
		rank = same;
		co_cdm -> do_cdm [ style=invis ];
		rankdir = LR;
	}
}

-------------------------------------------------------------------

If we consider this the "official" model, then we can start optimizing
cache operations, and start forbidding some nonsensical operations.

What do y'all think?

Andrew
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24  6:59       ` Christoph Hellwig
  2019-07-24  8:08         ` Benjamin Gaignard
  2019-07-24 11:38         ` Laura Abbott
@ 2019-07-24 15:46         ` Andrew F. Davis
  2019-07-25 12:50           ` Christoph Hellwig
  2019-07-24 18:46           ` John Stultz
  3 siblings, 1 reply; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-24 15:46 UTC (permalink / raw)
  To: Christoph Hellwig, John Stultz
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/24/19 2:59 AM, Christoph Hellwig wrote:
> On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
>> Apologies, I'm not sure I'm understanding your suggestion here.
>> dma_alloc_contiguous() does have some interesting optimizations
>> (avoiding allocating single page from cma), though its focus on
>> default area vs specific device area doesn't quite match up the usage
>> model for dma heaps.  Instead of allocating memory for a single
>> device, we want to be able to allow userland, for a given usage mode,
>> to be able to allocate a dmabuf from a specific heap of memory which
>> will satisfy the usage mode for that buffer pipeline (across multiple
>> devices).
>>
>> Now, indeed, the system and cma heaps in this patchset are a bit
>> simple/trivial (though useful with my devices that require contiguous
>> buffers for the display driver), but more complex ION heaps have
>> traditionally stayed out of tree in vendor code, in many cases making
>> incompatible tweaks to the ION core dmabuf exporter logic.
> 
> So what would the more complicated heaps be?
> 


https://patchwork.kernel.org/patch/10863957/

It's actually a more simple heap type IMHO, but the logic inside is
incompatible with the system/CMA heaps, if you move any of their code
into the core framework then this heap stops working. Leading to out of
tree hacks on the core to get it back functional. I see the same for the
"complex" heaps with ION.

Andrew


>> That's why
>> dmabuf heaps is trying to destage ION in a way that allows heaps to
>> implement their exporter logic themselves, so we can start pulling
>> those more complicated heaps out of their vendor hidey-holes and get
>> some proper upstream review.
>>
>> But I suspect I just am confused as to what your suggesting. Maybe
>> could you expand a bit? Apologies for being a bit dense.
> 
> My suggestion is to merge the system and CMA heaps.  CMA (at least
> the system-wide CMA area) is really just an optimization to get
> large contigous regions more easily.  We should make use of it as
> transparent as possible, just like we do in the DMA code.
> 

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24  6:59       ` Christoph Hellwig
@ 2019-07-24 18:46           ` John Stultz
  2019-07-24 11:38         ` Laura Abbott
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-24 18:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 12:00 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
> > Apologies, I'm not sure I'm understanding your suggestion here.
> > dma_alloc_contiguous() does have some interesting optimizations
> > (avoiding allocating single page from cma), though its focus on
> > default area vs specific device area doesn't quite match up the usage
> > model for dma heaps.  Instead of allocating memory for a single
> > device, we want to be able to allow userland, for a given usage mode,
> > to be able to allocate a dmabuf from a specific heap of memory which
> > will satisfy the usage mode for that buffer pipeline (across multiple
> > devices).
> >
> > Now, indeed, the system and cma heaps in this patchset are a bit
> > simple/trivial (though useful with my devices that require contiguous
> > buffers for the display driver), but more complex ION heaps have
> > traditionally stayed out of tree in vendor code, in many cases making
> > incompatible tweaks to the ION core dmabuf exporter logic.
>
> So what would the more complicated heaps be?

Mostly secure heaps, but there have been work in the past with
specially aligned chunk heaps in the past. Unfortunately since every
vendor tree also include many of their own hacks to the core ION code
(usually without changelogs or comments) its hard to decipher much of
it.

Some examples:
msm:
https://github.com/Panchajanya1999/msm-4.14/blob/Pie/drivers/staging/android/ion/ion_cma_secure_heap.c

exynos:
https://github.com/exynos-linux-stable/starlte/tree/tw90-android-p/drivers/staging/android/ion/exynos

hisi:
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_seccm_heap.c
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_secsg_heap.c
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_fama_misc_heap.c

mediatek:
https://android.googlesource.com/kernel/mediatek/+/android-mtk-3.18/drivers/staging/android/ion/mtk/ion_mm_heap.c

But Andrew's example is probably a better example against the dmabuf
heaps frameworks


> > That's why
> > dmabuf heaps is trying to destage ION in a way that allows heaps to
> > implement their exporter logic themselves, so we can start pulling
> > those more complicated heaps out of their vendor hidey-holes and get
> > some proper upstream review.
> >
> > But I suspect I just am confused as to what your suggesting. Maybe
> > could you expand a bit? Apologies for being a bit dense.
>
> My suggestion is to merge the system and CMA heaps.  CMA (at least
> the system-wide CMA area) is really just an optimization to get
> large contigous regions more easily.  We should make use of it as
> transparent as possible, just like we do in the DMA code.

I'm still not understanding how this would work. Benjamin and Laura
already commented on this point, but for a simple example, with the
HiKey boards, the DRM driver requires contiguous memory for the
framebuffer, but the GPU can handle non-contiguous. Thus the target
framebuffers that we pass to the display has to be CMA allocated, but
all the other graphics buffers that the GPU will render to and
composite can be system.

Having the separate heaps allows the gralloc code to allocate the
proper buffer depending on the planned usage (GRALLOC_USAGE_HW_FB or
not), and that way we don't waste CMA on buffers that don't have to be
contiguous.

Laura already touched on this, but similar logic can be used for
camera buffers, which can make sure we allocate from a specifically
reserved CMA region that is only used for the camera so we can always
be sure to have N free buffers immediately to capture with, etc.

But let me know if I'm still misunderstanding your suggestion.

thanks
-john

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
@ 2019-07-24 18:46           ` John Stultz
  0 siblings, 0 replies; 53+ messages in thread
From: John Stultz @ 2019-07-24 18:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Vincent Donnefort,
	Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Alistair Strachan,
	Xiaqing (A),
	Andrew F . Davis, Pratik Patel, butao

On Wed, Jul 24, 2019 at 12:00 AM Christoph Hellwig <hch@infradead.org> wrote:
> On Mon, Jul 22, 2019 at 10:04:06PM -0700, John Stultz wrote:
> > Apologies, I'm not sure I'm understanding your suggestion here.
> > dma_alloc_contiguous() does have some interesting optimizations
> > (avoiding allocating single page from cma), though its focus on
> > default area vs specific device area doesn't quite match up the usage
> > model for dma heaps.  Instead of allocating memory for a single
> > device, we want to be able to allow userland, for a given usage mode,
> > to be able to allocate a dmabuf from a specific heap of memory which
> > will satisfy the usage mode for that buffer pipeline (across multiple
> > devices).
> >
> > Now, indeed, the system and cma heaps in this patchset are a bit
> > simple/trivial (though useful with my devices that require contiguous
> > buffers for the display driver), but more complex ION heaps have
> > traditionally stayed out of tree in vendor code, in many cases making
> > incompatible tweaks to the ION core dmabuf exporter logic.
>
> So what would the more complicated heaps be?

Mostly secure heaps, but there have been work in the past with
specially aligned chunk heaps in the past. Unfortunately since every
vendor tree also include many of their own hacks to the core ION code
(usually without changelogs or comments) its hard to decipher much of
it.

Some examples:
msm:
https://github.com/Panchajanya1999/msm-4.14/blob/Pie/drivers/staging/android/ion/ion_cma_secure_heap.c

exynos:
https://github.com/exynos-linux-stable/starlte/tree/tw90-android-p/drivers/staging/android/ion/exynos

hisi:
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_seccm_heap.c
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_secsg_heap.c
https://github.com/hexdebug/android_kernel_huawei_hi3660/blob/master/drivers/staging/android/ion/ion_fama_misc_heap.c

mediatek:
https://android.googlesource.com/kernel/mediatek/+/android-mtk-3.18/drivers/staging/android/ion/mtk/ion_mm_heap.c

But Andrew's example is probably a better example against the dmabuf
heaps frameworks


> > That's why
> > dmabuf heaps is trying to destage ION in a way that allows heaps to
> > implement their exporter logic themselves, so we can start pulling
> > those more complicated heaps out of their vendor hidey-holes and get
> > some proper upstream review.
> >
> > But I suspect I just am confused as to what your suggesting. Maybe
> > could you expand a bit? Apologies for being a bit dense.
>
> My suggestion is to merge the system and CMA heaps.  CMA (at least
> the system-wide CMA area) is really just an optimization to get
> large contigous regions more easily.  We should make use of it as
> transparent as possible, just like we do in the DMA code.

I'm still not understanding how this would work. Benjamin and Laura
already commented on this point, but for a simple example, with the
HiKey boards, the DRM driver requires contiguous memory for the
framebuffer, but the GPU can handle non-contiguous. Thus the target
framebuffers that we pass to the display has to be CMA allocated, but
all the other graphics buffers that the GPU will render to and
composite can be system.

Having the separate heaps allows the gralloc code to allocate the
proper buffer depending on the planned usage (GRALLOC_USAGE_HW_FB or
not), and that way we don't waste CMA on buffers that don't have to be
contiguous.

Laura already touched on this, but similar logic can be used for
camera buffers, which can make sure we allocate from a specifically
reserved CMA region that is only used for the camera so we can always
be sure to have N free buffers immediately to capture with, etc.

But let me know if I'm still misunderstanding your suggestion.

thanks
-john
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-24 15:20             ` Andrew F. Davis
@ 2019-07-25 12:41               ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:41 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, Rob Clark, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju

On Wed, Jul 24, 2019 at 11:20:31AM -0400, Andrew F. Davis wrote:
> Well then lets think on this. A given buffer can have 3 owners states
> (CPU-owned, Device-owned, and Un-owned). These are based on the caching
> state from the CPU perspective.
> 
> If a buffer is CPU-owned then we (Linux) can write to the buffer safely
> without worry that the data is stale or that it will be accessed by the
> device without having been flushed. Device-owned buffers should not be
> accessed by the CPU, and inter-device synchronization should be handled
> by fencing as Rob points out. Un-owned is how a buffer starts for
> consistency and to prevent unneeded cache operations on unwritten buffers.

CPU owned also needs to be split into which mapping owns it - in the
normal DMA this is the kernel direct mapping, but in dma-buf it seems
the primary way of using it in kernel space is the vmap, in addition
to that the mappings can also be exported to userspace, which is another
mapping that is possibly not cache coherent with the kernel one.

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-25 12:41               ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:41 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, Rob Clark, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 11:20:31AM -0400, Andrew F. Davis wrote:
> Well then lets think on this. A given buffer can have 3 owners states
> (CPU-owned, Device-owned, and Un-owned). These are based on the caching
> state from the CPU perspective.
> 
> If a buffer is CPU-owned then we (Linux) can write to the buffer safely
> without worry that the data is stale or that it will be accessed by the
> device without having been flushed. Device-owned buffers should not be
> accessed by the CPU, and inter-device synchronization should be handled
> by fencing as Rob points out. Un-owned is how a buffer starts for
> consistency and to prevent unneeded cache operations on unwritten buffers.

CPU owned also needs to be split into which mapping owns it - in the
normal DMA this is the kernel direct mapping, but in dma-buf it seems
the primary way of using it in kernel space is the vmap, in addition
to that the mappings can also be exported to userspace, which is another
mapping that is possibly not cache coherent with the kernel one.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24  8:08         ` Benjamin Gaignard
@ 2019-07-25 12:45           ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:45 UTC (permalink / raw)
  To: Benjamin Gaignard
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Xu YiPing, Chenfeng (puck),
	butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 10:08:54AM +0200, Benjamin Gaignard wrote:
> CMA has made possible to get large regions of memories and to give some
> priority on device allocating pages on it. I don't think that possible
> with system
> heap so I suggest to keep CMA heap if we want to be able to port a maximum
> of applications on dma-buf-heap.

Yes, CMA is a way to better allocate contigous regions, but it isn't
the only way to do that.

So at least for the system default CMA area it really should be a helper
for the system heap, especially given that CMA is an optional feature
and we can do high order contigous allocations using alloc_pages as
well.

Something like:

	if (!require_contigous && order > 0) {
		for (i = 0; i < nr_pages; i++)
			page[i] = alloc_page();
		goto done;
	} else if (order > 0)
		page = cma_alloc();
		if (page)
			goto done;
	}

	page = alloc_pages(order);

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24 11:38         ` Laura Abbott
@ 2019-07-25 12:48           ` Christoph Hellwig
  2019-07-25 13:47               ` Andrew F. Davis
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:48 UTC (permalink / raw)
  To: Laura Abbott
  Cc: Christoph Hellwig, John Stultz, lkml, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 07:38:07AM -0400, Laura Abbott wrote:
> It's not just an optimization for Ion though. Ion was designed to
> let the callers choose between system and multiple CMA heaps.

Who cares about ion?  That some out of tree android crap that should
not be relevant for upstream except as an example for how not to design
things..

> On other
> systems there may be multiple CMA regions dedicated to a specific
> purpose or placed at a specific address. The callers need to
> be able to choose exactly whether they want a particular CMA region
> or discontiguous regions.

At least in cma is only used either with the global pool or a per-device
cma pool.  I think if you want to make this new dma-buf API fit in with
the rest with the kernel you follow that model, and pass in a struct
device to select the particular cma area, similar how the DMA allocator
works.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24 15:46         ` Andrew F. Davis
@ 2019-07-25 12:50           ` Christoph Hellwig
  2019-07-25 13:31               ` Andrew F. Davis
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:50 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 11:46:01AM -0400, Andrew F. Davis wrote:
> https://patchwork.kernel.org/patch/10863957/
> 
> It's actually a more simple heap type IMHO, but the logic inside is
> incompatible with the system/CMA heaps, if you move any of their code
> into the core framework then this heap stops working. Leading to out of
> tree hacks on the core to get it back functional. I see the same for the
> "complex" heaps with ION.

Well, this mostly is just another allocator (gen_pool).  And given that
the whole dma-buf infrastucture assumes things are backed by pages we
really shouldn't need much more than an alloc and a free callback (and
maybe the pgprot to map it) and handle the rest in common code.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-24 18:46           ` John Stultz
  (?)
@ 2019-07-25 12:52           ` Christoph Hellwig
  2019-07-25 13:20             ` Benjamin Gaignard
  -1 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 12:52 UTC (permalink / raw)
  To: John Stultz
  Cc: Christoph Hellwig, lkml, Laura Abbott, Benjamin Gaignard,
	Sumit Semwal, Liam Mark, Pratik Patel, Brian Starkey,
	Vincent Donnefort, Sudipto Paul, Andrew F . Davis, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Wed, Jul 24, 2019 at 11:46:24AM -0700, John Stultz wrote:
> I'm still not understanding how this would work. Benjamin and Laura
> already commented on this point, but for a simple example, with the
> HiKey boards, the DRM driver requires contiguous memory for the
> framebuffer, but the GPU can handle non-contiguous. Thus the target
> framebuffers that we pass to the display has to be CMA allocated, but
> all the other graphics buffers that the GPU will render to and
> composite can be system.

But that just means we need a flag that memory needs to be contiguous,
which totally makes sense at the API level.  But CMA is not the only
source of contigous memory, so we should not conflate the two.

> Laura already touched on this, but similar logic can be used for
> camera buffers, which can make sure we allocate from a specifically
> reserved CMA region that is only used for the camera so we can always
> be sure to have N free buffers immediately to capture with, etc.

And for that we already have per-device CMA areas hanging off struct
device, which this should reuse instead of adding another duplicate
CMA area lookup scheme.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 12:52           ` Christoph Hellwig
@ 2019-07-25 13:20             ` Benjamin Gaignard
  2019-07-25 14:33               ` Christoph Hellwig
  0 siblings, 1 reply; 53+ messages in thread
From: Benjamin Gaignard @ 2019-07-25 13:20 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

Le jeu. 25 juil. 2019 à 14:52, Christoph Hellwig <hch@infradead.org> a écrit :
>
> On Wed, Jul 24, 2019 at 11:46:24AM -0700, John Stultz wrote:
> > I'm still not understanding how this would work. Benjamin and Laura
> > already commented on this point, but for a simple example, with the
> > HiKey boards, the DRM driver requires contiguous memory for the
> > framebuffer, but the GPU can handle non-contiguous. Thus the target
> > framebuffers that we pass to the display has to be CMA allocated, but
> > all the other graphics buffers that the GPU will render to and
> > composite can be system.

No we have uses cases where graphic buffers can go directly to display without
using GPU. For example we can grab frames from the camera and send them directly
in display (same for video decoder) because we have planes for that.

>
> But that just means we need a flag that memory needs to be contiguous,
> which totally makes sense at the API level.  But CMA is not the only
> source of contigous memory, so we should not conflate the two.

We have one file descriptor per heap to be able to add access control
on each heap.
That wasn't possible with ION because the heap was selected given the
flags in ioctl
structure and we can't do access control based on that. If we put flag
to select the
allocation mechanism (system, CMA, other) in ioctl we come back to ION status.
For me one allocation mechanism = one heap.

>
> > Laura already touched on this, but similar logic can be used for
> > camera buffers, which can make sure we allocate from a specifically
> > reserved CMA region that is only used for the camera so we can always
> > be sure to have N free buffers immediately to capture with, etc.
>
> And for that we already have per-device CMA areas hanging off struct
> device, which this should reuse instead of adding another duplicate
> CMA area lookup scheme.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 12:50           ` Christoph Hellwig
@ 2019-07-25 13:31               ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 13:31 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/25/19 8:50 AM, Christoph Hellwig wrote:
> On Wed, Jul 24, 2019 at 11:46:01AM -0400, Andrew F. Davis wrote:
>> https://patchwork.kernel.org/patch/10863957/
>>
>> It's actually a more simple heap type IMHO, but the logic inside is
>> incompatible with the system/CMA heaps, if you move any of their code
>> into the core framework then this heap stops working. Leading to out of
>> tree hacks on the core to get it back functional. I see the same for the
>> "complex" heaps with ION.
> 
> Well, this mostly is just another allocator (gen_pool).  And given that
> the whole dma-buf infrastucture assumes things are backed by pages we
> really shouldn't need much more than an alloc and a free callback (and
> maybe the pgprot to map it) and handle the rest in common code.
> 

But that's just it, dma-buf does not assume buffers are backed by normal
kernel managed memory, it is up to the buffer exporter where and when to
allocate the memory. The memory backed by this SRAM buffer does not have
the normal struct page backing. So moving the map, sync, etc functions
to common code would fail for this and many other heap types. This was a
major problem with Ion that prompted this new design.

Each heap type may need to do something different depending on its
backing memory, moving everything to common code that is common to
System and CMA heaps is would lead those being the only upstreamable heaps.

Andrew

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
@ 2019-07-25 13:31               ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 13:31 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Alistair Strachan,
	Vincent Donnefort, Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Xiaqing (A),
	Pratik Patel, butao

On 7/25/19 8:50 AM, Christoph Hellwig wrote:
> On Wed, Jul 24, 2019 at 11:46:01AM -0400, Andrew F. Davis wrote:
>> https://patchwork.kernel.org/patch/10863957/
>>
>> It's actually a more simple heap type IMHO, but the logic inside is
>> incompatible with the system/CMA heaps, if you move any of their code
>> into the core framework then this heap stops working. Leading to out of
>> tree hacks on the core to get it back functional. I see the same for the
>> "complex" heaps with ION.
> 
> Well, this mostly is just another allocator (gen_pool).  And given that
> the whole dma-buf infrastucture assumes things are backed by pages we
> really shouldn't need much more than an alloc and a free callback (and
> maybe the pgprot to map it) and handle the rest in common code.
> 

But that's just it, dma-buf does not assume buffers are backed by normal
kernel managed memory, it is up to the buffer exporter where and when to
allocate the memory. The memory backed by this SRAM buffer does not have
the normal struct page backing. So moving the map, sync, etc functions
to common code would fail for this and many other heap types. This was a
major problem with Ion that prompted this new design.

Each heap type may need to do something different depending on its
backing memory, moving everything to common code that is common to
System and CMA heaps is would lead those being the only upstreamable heaps.

Andrew
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 12:48           ` Christoph Hellwig
@ 2019-07-25 13:47               ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 13:47 UTC (permalink / raw)
  To: Christoph Hellwig, Laura Abbott
  Cc: John Stultz, lkml, Benjamin Gaignard, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/25/19 8:48 AM, Christoph Hellwig wrote:
> On Wed, Jul 24, 2019 at 07:38:07AM -0400, Laura Abbott wrote:
>> It's not just an optimization for Ion though. Ion was designed to
>> let the callers choose between system and multiple CMA heaps.
> 
> Who cares about ion?  That some out of tree android crap that should
> not be relevant for upstream except as an example for how not to design
> things..
> 

Tell us how you really feel about ION :)

>> On other
>> systems there may be multiple CMA regions dedicated to a specific
>> purpose or placed at a specific address. The callers need to
>> be able to choose exactly whether they want a particular CMA region
>> or discontiguous regions.
> 
> At least in cma is only used either with the global pool or a per-device
> cma pool.  I think if you want to make this new dma-buf API fit in with
> the rest with the kernel you follow that model, and pass in a struct
> device to select the particular cma area, similar how the DMA allocator
> works.
> 

This is a central allocator, it is not tied to any one device. If we
knew the one device ahead of time we would just use the existing dma_alloc.

We might be able to solve some of that with late mapping after all the
devices attach to the buffer, but even then, which device's CMA area
would we chose to use from all the attached devices?

I can agree that allocating from per-device CMA using Heaps doesn't make
much sense, but for global pools I'm not sure I see any way to allow
devices to select which pool is right for a specific use. They don't
have the full use-case information like the application does, the
selection needs to be made from the application.

Andrew

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
@ 2019-07-25 13:47               ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 13:47 UTC (permalink / raw)
  To: Christoph Hellwig, Laura Abbott
  Cc: Yudongbin, Alistair Strachan, Xu YiPing, Vincent Donnefort,
	Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Xiaqing (A),
	Sudipto Paul, Pratik Patel, butao

On 7/25/19 8:48 AM, Christoph Hellwig wrote:
> On Wed, Jul 24, 2019 at 07:38:07AM -0400, Laura Abbott wrote:
>> It's not just an optimization for Ion though. Ion was designed to
>> let the callers choose between system and multiple CMA heaps.
> 
> Who cares about ion?  That some out of tree android crap that should
> not be relevant for upstream except as an example for how not to design
> things..
> 

Tell us how you really feel about ION :)

>> On other
>> systems there may be multiple CMA regions dedicated to a specific
>> purpose or placed at a specific address. The callers need to
>> be able to choose exactly whether they want a particular CMA region
>> or discontiguous regions.
> 
> At least in cma is only used either with the global pool or a per-device
> cma pool.  I think if you want to make this new dma-buf API fit in with
> the rest with the kernel you follow that model, and pass in a struct
> device to select the particular cma area, similar how the DMA allocator
> works.
> 

This is a central allocator, it is not tied to any one device. If we
knew the one device ahead of time we would just use the existing dma_alloc.

We might be able to solve some of that with late mapping after all the
devices attach to the buffer, but even then, which device's CMA area
would we chose to use from all the attached devices?

I can agree that allocating from per-device CMA using Heaps doesn't make
much sense, but for global pools I'm not sure I see any way to allow
devices to select which pool is right for a specific use. They don't
have the full use-case information like the application does, the
selection needs to be made from the application.

Andrew
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 13:31               ` Andrew F. Davis
  (?)
@ 2019-07-25 14:04               ` Christoph Hellwig
  2019-07-25 14:10                 ` Andrew F. Davis
  -1 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 14:04 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 25, 2019 at 09:31:50AM -0400, Andrew F. Davis wrote:
> But that's just it, dma-buf does not assume buffers are backed by normal
> kernel managed memory, it is up to the buffer exporter where and when to
> allocate the memory. The memory backed by this SRAM buffer does not have
> the normal struct page backing. So moving the map, sync, etc functions
> to common code would fail for this and many other heap types. This was a
> major problem with Ion that prompted this new design.

The code clearly shows it has page backing, e.g. this:

+	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);

and the fact that it (and the dma-buf API) uses scatterlists, which 
requires pages.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 13:47               ` Andrew F. Davis
  (?)
@ 2019-07-25 14:05               ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 14:05 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, Laura Abbott, John Stultz, lkml,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 25, 2019 at 09:47:11AM -0400, Andrew F. Davis wrote:
> This is a central allocator, it is not tied to any one device. If we
> knew the one device ahead of time we would just use the existing dma_alloc.
> 
> We might be able to solve some of that with late mapping after all the
> devices attach to the buffer, but even then, which device's CMA area
> would we chose to use from all the attached devices?
> 
> I can agree that allocating from per-device CMA using Heaps doesn't make
> much sense, but for global pools I'm not sure I see any way to allow
> devices to select which pool is right for a specific use. They don't
> have the full use-case information like the application does, the
> selection needs to be made from the application.

Well, the examples we had before was that we clear want to use the
per-device CMA area.  And at least in upstream a CMA area either is
global or attached to a device, as we otherwise wouldn't find it.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:04               ` Christoph Hellwig
@ 2019-07-25 14:10                 ` Andrew F. Davis
  2019-07-25 14:11                   ` Christoph Hellwig
  0 siblings, 1 reply; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 14:10 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/25/19 10:04 AM, Christoph Hellwig wrote:
> On Thu, Jul 25, 2019 at 09:31:50AM -0400, Andrew F. Davis wrote:
>> But that's just it, dma-buf does not assume buffers are backed by normal
>> kernel managed memory, it is up to the buffer exporter where and when to
>> allocate the memory. The memory backed by this SRAM buffer does not have
>> the normal struct page backing. So moving the map, sync, etc functions
>> to common code would fail for this and many other heap types. This was a
>> major problem with Ion that prompted this new design.
> 
> The code clearly shows it has page backing, e.g. this:
> 
> +	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
> 
> and the fact that it (and the dma-buf API) uses scatterlists, which 
> requires pages.
> 

Pages yes, but not "normal" pages from the kernel managed area.
page_to_pfn() will return bad values on the pages returned by this
allocator and so will any of the kernel sync/map functions. Therefor
those operations cannot be common and need special per-heap handling.

Andrew

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:10                 ` Andrew F. Davis
@ 2019-07-25 14:11                   ` Christoph Hellwig
  2019-07-25 14:25                     ` Andrew F. Davis
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 14:11 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 25, 2019 at 10:10:08AM -0400, Andrew F. Davis wrote:
> Pages yes, but not "normal" pages from the kernel managed area.
> page_to_pfn() will return bad values on the pages returned by this
> allocator and so will any of the kernel sync/map functions. Therefor
> those operations cannot be common and need special per-heap handling.

Well, that means this thing is buggy and abuses the scatterlist API
and we can't merge it anyway, so it is irrelevant.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:11                   ` Christoph Hellwig
@ 2019-07-25 14:25                     ` Andrew F. Davis
  2019-07-25 14:30                       ` Christoph Hellwig
  0 siblings, 1 reply; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 14:25 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/25/19 10:11 AM, Christoph Hellwig wrote:
> On Thu, Jul 25, 2019 at 10:10:08AM -0400, Andrew F. Davis wrote:
>> Pages yes, but not "normal" pages from the kernel managed area.
>> page_to_pfn() will return bad values on the pages returned by this
>> allocator and so will any of the kernel sync/map functions. Therefor
>> those operations cannot be common and need special per-heap handling.
> 
> Well, that means this thing is buggy and abuses the scatterlist API
> and we can't merge it anyway, so it is irrelevant.
> 

Since when do scatterlists need to only have kernel virtual backed
memory pages? Device memory is stored in scatterlists and
dma_sync_sg_for_* would fail just the same when the cache ops were
attempted.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:25                     ` Andrew F. Davis
@ 2019-07-25 14:30                       ` Christoph Hellwig
  2019-07-25 14:51                           ` Andrew F. Davis
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 14:30 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 25, 2019 at 10:25:50AM -0400, Andrew F. Davis wrote:
> On 7/25/19 10:11 AM, Christoph Hellwig wrote:
> > On Thu, Jul 25, 2019 at 10:10:08AM -0400, Andrew F. Davis wrote:
> >> Pages yes, but not "normal" pages from the kernel managed area.
> >> page_to_pfn() will return bad values on the pages returned by this
> >> allocator and so will any of the kernel sync/map functions. Therefor
> >> those operations cannot be common and need special per-heap handling.
> > 
> > Well, that means this thing is buggy and abuses the scatterlist API
> > and we can't merge it anyway, so it is irrelevant.
> > 
> 
> Since when do scatterlists need to only have kernel virtual backed
> memory pages? Device memory is stored in scatterlists and
> dma_sync_sg_for_* would fail just the same when the cache ops were
> attempted.

I'm not sure what you mean with virtual backed memory pages, as we
don't really have that concept.

But a page in the scatterlist needs to be able to be used everywhere
we'd normally use a page, e.g. page_to_phys, page_to_pfn, kmap,
page_address (if !highmem) as consumers including the dma mapping
interface do all that.

If you want to dma map memory that does not have page backing you
need to use dma_map_resource.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 13:20             ` Benjamin Gaignard
@ 2019-07-25 14:33               ` Christoph Hellwig
  2019-07-25 14:46                 ` Benjamin Gaignard
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2019-07-25 14:33 UTC (permalink / raw)
  To: Benjamin Gaignard
  Cc: Christoph Hellwig, John Stultz, lkml, Laura Abbott, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Andrew F . Davis, Xu YiPing, Chenfeng (puck),
	butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On Thu, Jul 25, 2019 at 03:20:11PM +0200, Benjamin Gaignard wrote:
> > But that just means we need a flag that memory needs to be contiguous,
> > which totally makes sense at the API level.  But CMA is not the only
> > source of contigous memory, so we should not conflate the two.
> 
> We have one file descriptor per heap to be able to add access control
> on each heap.
> That wasn't possible with ION because the heap was selected given the
> flags in ioctl
> structure and we can't do access control based on that. If we put flag
> to select the
> allocation mechanism (system, CMA, other) in ioctl we come back to ION status.
> For me one allocation mechanism = one heap.

Well, I agree with your split for different fundamentally different
allocators.  But the point is that CMA (at least the system cma area)
fundamentally isn't a different allocator.  The per-device CMA area
still are kinda the same, but you can just have one fd for each
per-device CMA area to make your life simple.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:33               ` Christoph Hellwig
@ 2019-07-25 14:46                 ` Benjamin Gaignard
  0 siblings, 0 replies; 53+ messages in thread
From: Benjamin Gaignard @ 2019-07-25 14:46 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Sumit Semwal, Liam Mark,
	Pratik Patel, Brian Starkey, Vincent Donnefort, Sudipto Paul,
	Andrew F . Davis, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

Le jeu. 25 juil. 2019 à 16:33, Christoph Hellwig <hch@infradead.org> a écrit :
>
> On Thu, Jul 25, 2019 at 03:20:11PM +0200, Benjamin Gaignard wrote:
> > > But that just means we need a flag that memory needs to be contiguous,
> > > which totally makes sense at the API level.  But CMA is not the only
> > > source of contigous memory, so we should not conflate the two.
> >
> > We have one file descriptor per heap to be able to add access control
> > on each heap.
> > That wasn't possible with ION because the heap was selected given the
> > flags in ioctl
> > structure and we can't do access control based on that. If we put flag
> > to select the
> > allocation mechanism (system, CMA, other) in ioctl we come back to ION status.
> > For me one allocation mechanism = one heap.
>
> Well, I agree with your split for different fundamentally different
> allocators.  But the point is that CMA (at least the system cma area)
> fundamentally isn't a different allocator.  The per-device CMA area
> still are kinda the same, but you can just have one fd for each
> per-device CMA area to make your life simple.

Form my point of view default cma area is a specific allocator because
it could migrate page to give them in priority to contigous allocation. It is
also one of the last region where system page are going to be allocated.
I don't think that system allocator does have the same features, either we
would have use it rather develop CMA years ago ;-). In short CMA had
solved lot of problems on our side so it had to have it own heap.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
  2019-07-25 14:30                       ` Christoph Hellwig
@ 2019-07-25 14:51                           ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 14:51 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: John Stultz, lkml, Laura Abbott, Benjamin Gaignard, Sumit Semwal,
	Liam Mark, Pratik Patel, Brian Starkey, Vincent Donnefort,
	Sudipto Paul, Xu YiPing, Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel

On 7/25/19 10:30 AM, Christoph Hellwig wrote:
> On Thu, Jul 25, 2019 at 10:25:50AM -0400, Andrew F. Davis wrote:
>> On 7/25/19 10:11 AM, Christoph Hellwig wrote:
>>> On Thu, Jul 25, 2019 at 10:10:08AM -0400, Andrew F. Davis wrote:
>>>> Pages yes, but not "normal" pages from the kernel managed area.
>>>> page_to_pfn() will return bad values on the pages returned by this
>>>> allocator and so will any of the kernel sync/map functions. Therefor
>>>> those operations cannot be common and need special per-heap handling.
>>>
>>> Well, that means this thing is buggy and abuses the scatterlist API
>>> and we can't merge it anyway, so it is irrelevant.
>>>
>>
>> Since when do scatterlists need to only have kernel virtual backed
>> memory pages? Device memory is stored in scatterlists and
>> dma_sync_sg_for_* would fail just the same when the cache ops were
>> attempted.
> 
> I'm not sure what you mean with virtual backed memory pages, as we
> don't really have that concept.
> 
> But a page in the scatterlist needs to be able to be used everywhere
> we'd normally use a page, e.g. page_to_phys, page_to_pfn, kmap,
> page_address (if !highmem) as consumers including the dma mapping
> interface do all that.
> 
> If you want to dma map memory that does not have page backing you
> need to use dma_map_resource.
> 

I probably should have worded that better.

It does have page backing, what I meant by "page_to_pfn() will return
bad values" is not that it won't give you the correct pfn, it will, but
that then that pfn is not part of the normal memory space
(lowmem/highmem) it's device memory, so cache ops won't work. But you
should not be doing that on device memory anyway.

That is a problem with Ion I want to avoid, it assumed all buffers were
in DDR and so would do cache operations on them unconditionally, too
many assumptions were made as too much was moved into the common core
code and not enough was left for the heaps themselves to decide.

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

* Re: [PATCH v6 4/5] dma-buf: heaps: Add CMA heap to dmabuf heaps
@ 2019-07-25 14:51                           ` Andrew F. Davis
  0 siblings, 0 replies; 53+ messages in thread
From: Andrew F. Davis @ 2019-07-25 14:51 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Yudongbin, Sudipto Paul, Xu YiPing, Alistair Strachan,
	Vincent Donnefort, Chenfeng (puck),
	dri-devel, Chenbo Feng, lkml, Liam Mark, Xiaqing (A),
	Pratik Patel, butao

On 7/25/19 10:30 AM, Christoph Hellwig wrote:
> On Thu, Jul 25, 2019 at 10:25:50AM -0400, Andrew F. Davis wrote:
>> On 7/25/19 10:11 AM, Christoph Hellwig wrote:
>>> On Thu, Jul 25, 2019 at 10:10:08AM -0400, Andrew F. Davis wrote:
>>>> Pages yes, but not "normal" pages from the kernel managed area.
>>>> page_to_pfn() will return bad values on the pages returned by this
>>>> allocator and so will any of the kernel sync/map functions. Therefor
>>>> those operations cannot be common and need special per-heap handling.
>>>
>>> Well, that means this thing is buggy and abuses the scatterlist API
>>> and we can't merge it anyway, so it is irrelevant.
>>>
>>
>> Since when do scatterlists need to only have kernel virtual backed
>> memory pages? Device memory is stored in scatterlists and
>> dma_sync_sg_for_* would fail just the same when the cache ops were
>> attempted.
> 
> I'm not sure what you mean with virtual backed memory pages, as we
> don't really have that concept.
> 
> But a page in the scatterlist needs to be able to be used everywhere
> we'd normally use a page, e.g. page_to_phys, page_to_pfn, kmap,
> page_address (if !highmem) as consumers including the dma mapping
> interface do all that.
> 
> If you want to dma map memory that does not have page backing you
> need to use dma_map_resource.
> 

I probably should have worded that better.

It does have page backing, what I meant by "page_to_pfn() will return
bad values" is not that it won't give you the correct pfn, it will, but
that then that pfn is not part of the normal memory space
(lowmem/highmem) it's device memory, so cache ops won't work. But you
should not be doing that on device memory anyway.

That is a problem with Ion I want to avoid, it assumed all buffers were
in DDR and so would do cache operations on them unconditionally, too
many assumptions were made as too much was moved into the common core
code and not enough was left for the heaps themselves to decide.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
  2019-07-25 12:41               ` Christoph Hellwig
@ 2019-07-25 15:23                 ` Rob Clark
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Clark @ 2019-07-25 15:23 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Andrew F. Davis, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel,
	Hridya Valsaraju

On Thu, Jul 25, 2019 at 5:41 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Wed, Jul 24, 2019 at 11:20:31AM -0400, Andrew F. Davis wrote:
> > Well then lets think on this. A given buffer can have 3 owners states
> > (CPU-owned, Device-owned, and Un-owned). These are based on the caching
> > state from the CPU perspective.
> >
> > If a buffer is CPU-owned then we (Linux) can write to the buffer safely
> > without worry that the data is stale or that it will be accessed by the
> > device without having been flushed. Device-owned buffers should not be
> > accessed by the CPU, and inter-device synchronization should be handled
> > by fencing as Rob points out. Un-owned is how a buffer starts for
> > consistency and to prevent unneeded cache operations on unwritten buffers.
>
> CPU owned also needs to be split into which mapping owns it - in the
> normal DMA this is the kernel direct mapping, but in dma-buf it seems
> the primary way of using it in kernel space is the vmap, in addition
> to that the mappings can also be exported to userspace, which is another
> mapping that is possibly not cache coherent with the kernel one.

Just for some history, dmabuf->vmap() is optional, and mostly added
for the benefit of drm/udl (usb display, where CPU needs to read out
and encode (?) the video stream.. most of the drm drivers are using
tmpfs to get backing pages, and if there is any kernel direct mapping
it is unused.

It is probably ok for any allocator that does care about a kernel
direct mapping to simply not implement vmap.

BR,
-R

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

* Re: [PATCH v6 2/5] dma-buf: heaps: Add heap helpers
@ 2019-07-25 15:23                 ` Rob Clark
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Clark @ 2019-07-25 15:23 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Andrew F. Davis, John Stultz, lkml, Laura Abbott,
	Benjamin Gaignard, Sumit Semwal, Liam Mark, Pratik Patel,
	Brian Starkey, Vincent Donnefort, Sudipto Paul, Xu YiPing,
	Chenfeng (puck), butao, Xiaqing (A),
	Yudongbin, Chenbo Feng, Alistair Strachan, dri-devel, Hridy

On Thu, Jul 25, 2019 at 5:41 AM Christoph Hellwig <hch@infradead.org> wrote:
>
> On Wed, Jul 24, 2019 at 11:20:31AM -0400, Andrew F. Davis wrote:
> > Well then lets think on this. A given buffer can have 3 owners states
> > (CPU-owned, Device-owned, and Un-owned). These are based on the caching
> > state from the CPU perspective.
> >
> > If a buffer is CPU-owned then we (Linux) can write to the buffer safely
> > without worry that the data is stale or that it will be accessed by the
> > device without having been flushed. Device-owned buffers should not be
> > accessed by the CPU, and inter-device synchronization should be handled
> > by fencing as Rob points out. Un-owned is how a buffer starts for
> > consistency and to prevent unneeded cache operations on unwritten buffers.
>
> CPU owned also needs to be split into which mapping owns it - in the
> normal DMA this is the kernel direct mapping, but in dma-buf it seems
> the primary way of using it in kernel space is the vmap, in addition
> to that the mappings can also be exported to userspace, which is another
> mapping that is possibly not cache coherent with the kernel one.

Just for some history, dmabuf->vmap() is optional, and mostly added
for the benefit of drm/udl (usb display, where CPU needs to read out
and encode (?) the video stream.. most of the drm drivers are using
tmpfs to get backing pages, and if there is any kernel direct mapping
it is unused.

It is probably ok for any allocator that does care about a kernel
direct mapping to simply not implement vmap.

BR,
-R

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

end of thread, other threads:[~2019-07-25 15:24 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-24 19:49 [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) John Stultz
2019-06-24 19:49 ` [PATCH v6 1/5] dma-buf: Add dma-buf heaps framework John Stultz
2019-06-24 19:49 ` [PATCH v6 2/5] dma-buf: heaps: Add heap helpers John Stultz
2019-06-24 19:49   ` John Stultz
2019-07-18 10:06   ` Christoph Hellwig
2019-07-23  4:09     ` John Stultz
2019-07-23  4:09       ` John Stultz
2019-07-23 20:09       ` Rob Clark
2019-07-23 20:09         ` Rob Clark
2019-07-24  6:55         ` Christoph Hellwig
2019-07-24  6:55           ` Christoph Hellwig
2019-07-24 15:20           ` Andrew F. Davis
2019-07-24 15:20             ` Andrew F. Davis
2019-07-25 12:41             ` Christoph Hellwig
2019-07-25 12:41               ` Christoph Hellwig
2019-07-25 15:23               ` Rob Clark
2019-07-25 15:23                 ` Rob Clark
2019-07-24  6:58       ` Christoph Hellwig
2019-07-24  6:58         ` Christoph Hellwig
2019-06-24 19:49 ` [PATCH v6 3/5] dma-buf: heaps: Add system heap to dmabuf heaps John Stultz
2019-06-24 19:49 ` [PATCH v6 4/5] dma-buf: heaps: Add CMA " John Stultz
2019-07-18 10:08   ` Christoph Hellwig
2019-07-23  5:04     ` John Stultz
2019-07-23  5:04       ` John Stultz
2019-07-24  6:59       ` Christoph Hellwig
2019-07-24  8:08         ` Benjamin Gaignard
2019-07-25 12:45           ` Christoph Hellwig
2019-07-24 11:38         ` Laura Abbott
2019-07-25 12:48           ` Christoph Hellwig
2019-07-25 13:47             ` Andrew F. Davis
2019-07-25 13:47               ` Andrew F. Davis
2019-07-25 14:05               ` Christoph Hellwig
2019-07-24 15:46         ` Andrew F. Davis
2019-07-25 12:50           ` Christoph Hellwig
2019-07-25 13:31             ` Andrew F. Davis
2019-07-25 13:31               ` Andrew F. Davis
2019-07-25 14:04               ` Christoph Hellwig
2019-07-25 14:10                 ` Andrew F. Davis
2019-07-25 14:11                   ` Christoph Hellwig
2019-07-25 14:25                     ` Andrew F. Davis
2019-07-25 14:30                       ` Christoph Hellwig
2019-07-25 14:51                         ` Andrew F. Davis
2019-07-25 14:51                           ` Andrew F. Davis
2019-07-24 18:46         ` John Stultz
2019-07-24 18:46           ` John Stultz
2019-07-25 12:52           ` Christoph Hellwig
2019-07-25 13:20             ` Benjamin Gaignard
2019-07-25 14:33               ` Christoph Hellwig
2019-07-25 14:46                 ` Benjamin Gaignard
2019-06-24 19:49 ` [PATCH v6 5/5] kselftests: Add dma-heap test John Stultz
2019-06-24 19:49   ` John Stultz
2019-07-01 21:45 ` [PATCH v6 0/5] DMA-BUF Heaps (destaging ION) Laura Abbott
2019-07-01 21:55   ` John Stultz

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.