Message ID | 1551819273-640-2-git-send-email-john.stultz@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | DMA-BUF Heaps (destaging ION) | expand |
Le mar. 5 mars 2019 à 21:54, John Stultz <john.stultz@linaro.org> a écrit : > > 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: Greg KH <gregkh@linuxfoundation.org> > Cc: Sumit Semwal <sumit.semwal@linaro.org> > Cc: Liam Mark <lmark@codeaurora.org> > Cc: Brian Starkey <Brian.Starkey@arm.com> > Cc: Andrew F. Davis <afd@ti.com> > Cc: Chenbo Feng <fengc@google.com> > Cc: Alistair Strachan <astrachan@google.com> > Cc: dri-devel@lists.freedesktop.org > Signed-off-by: Andrew F. Davis <afd@ti.com> > [jstultz: reworded commit message, and lots of cleanups] > Signed-off-by: John Stultz <john.stultz@linaro.org> > --- > 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 then a buffer > (as it simplifies error handling) > --- > MAINTAINERS | 16 ++++ > drivers/dma-buf/Kconfig | 8 ++ > drivers/dma-buf/Makefile | 1 + > drivers/dma-buf/dma-heap.c | 191 ++++++++++++++++++++++++++++++++++++++++++ > include/linux/dma-heap.h | 65 ++++++++++++++ > include/uapi/linux/dma-heap.h | 52 ++++++++++++ > 6 files changed, 333 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 ac2e518..a661e19 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4621,6 +4621,22 @@ 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: Laura Abbott <labbott@redhat.com> > +R: Liam Mark <lmark@codeaurora.org> > +R: Brian Starkey <Brian.Starkey@arm.com> > +R: "Andrew F. Davis" <afd@ti.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 2e5a0fa..09c61db 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 0913a6c..b0332f1 100644 > --- a/drivers/dma-buf/Makefile > +++ b/drivers/dma-buf/Makefile > @@ -1,4 +1,5 @@ > obj-y := dma-buf.o dma-fence.o dma-fence-array.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 0000000..14b3975 > --- /dev/null > +++ b/drivers/dma-buf/dma-heap.c > @@ -0,0 +1,191 @@ > +// 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/idr.h> > +#include <linux/list.h> > +#include <linux/slab.h> > +#include <linux/uaccess.h> > + > +#include <linux/dma-heap.h> > +#include <uapi/linux/dma-heap.h> > + > +#define DEVNAME "dma_heap" > + > +#define NUM_HEAP_MINORS 128 > +static DEFINE_IDR(dma_heap_idr); > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ > + > +dev_t dma_heap_devt; > +struct class *dma_heap_class; > +struct list_head dma_heap_list; > +struct dentry *dma_heap_debug_root; > + > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > + unsigned int flags) > +{ > + len = PAGE_ALIGN(len); > + if (!len) > + return -EINVAL; > + > + return heap->ops->allocate(heap, len, flags); > +} > + > +static int dma_heap_open(struct inode *inode, struct file *filp) > +{ > + struct dma_heap *heap; > + > + mutex_lock(&minor_lock); > + heap = idr_find(&dma_heap_idr, iminor(inode)); > + mutex_unlock(&minor_lock); > + if (!heap) { > + pr_err("dma_heap: minor %d unknown.\n", iminor(inode)); > + return -ENODEV; > + } > + > + /* instance data as context */ > + filp->private_data = heap; > + nonseekable_open(inode, filp); > + > + return 0; > +} > + > +static int dma_heap_release(struct inode *inode, struct file *filp) > +{ > + filp->private_data = NULL; > + > + return 0; > +} > + > +static long dma_heap_ioctl(struct file *filp, unsigned int cmd, > + unsigned long arg) > +{ > + switch (cmd) { > + case DMA_HEAP_IOC_ALLOC: > + { > + struct dma_heap_allocation_data heap_allocation; > + struct dma_heap *heap = filp->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 || > + heap_allocation.reserved2) { > + pr_warn_once("dma_heap: ioctl data not valid\n"); > + return -EINVAL; > + } > + if (heap_allocation.flags & ~DMA_HEAP_VALID_FLAGS) { > + pr_warn_once("dma_heap: flags has invalid or unsupported flags set\n"); > + return -EINVAL; > + } > + > + fd = dma_heap_buffer_alloc(heap, heap_allocation.len, > + heap_allocation.flags); > + if (fd < 0) > + return fd; > + > + heap_allocation.fd = fd; > + > + if (copy_to_user((void __user *)arg, &heap_allocation, > + sizeof(heap_allocation))) > + return -EFAULT; > + > + break; > + } > + default: > + return -ENOTTY; > + } > + > + return 0; > +} > + > +static const struct file_operations dma_heap_fops = { > + .owner = THIS_MODULE, > + .open = dma_heap_open, > + .release = dma_heap_release, > + .unlocked_ioctl = dma_heap_ioctl, > +#ifdef CONFIG_COMPAT > + .compat_ioctl = dma_heap_ioctl, > +#endif > +}; > + > +int dma_heap_add(struct dma_heap *heap) > +{ > + struct device *dev_ret; > + int ret; > + > + if (!heap->name || !strcmp(heap->name, "")) { > + pr_err("dma_heap: Cannot add heap without a name\n"); > + return -EINVAL; > + } > + > + if (!heap->ops || !heap->ops->allocate) { > + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); > + return -EINVAL; > + } > + > + /* Find unused minor number */ > + mutex_lock(&minor_lock); > + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); > + mutex_unlock(&minor_lock); > + if (ret < 0) { > + pr_err("dma_heap: Unable to get minor number for heap\n"); > + return ret; > + } > + heap->minor = ret; > + > + /* Create device */ > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > + 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 char device\n"); > + return PTR_ERR(dev_ret); > + } > + > + /* Add device */ > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > + if (ret < 0) { > + device_destroy(dma_heap_class, heap->heap_devt); > + pr_err("dma_heap: Unable to add char device\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(dma_heap_add); > + > +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); > + } > + > + 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 0000000..ed86a8e > --- /dev/null > +++ b/include/linux/dma-heap.h > @@ -0,0 +1,65 @@ > +/* 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_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 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; > + unsigned int minor; > + dev_t heap_devt; > + struct cdev heap_cdev; > +}; > + > +/** > + * 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 flags); > +}; > + > +/** > + * dma_heap_add - adds a heap to dmabuf heaps > + * @heap: the heap to add > + */ > +int dma_heap_add(struct dma_heap *heap); > + > +#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 0000000..75c5d3f > --- /dev/null > +++ b/include/uapi/linux/dma-heap.h > @@ -0,0 +1,52 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * 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 > + * > + */ > + > +/* Currently no flags */ > +#define DMA_HEAP_VALID_FLAGS (0) I think here you need to allow flags like O_RDWR or O_CLOEXEC else mmap will fail. Benjamin > + > +/** > + * struct dma_heap_allocation_data - metadata passed from userspace for > + * allocations > + * @len: size of the allocation > + * @flags: flags passed to pool > + * @fd: will be populated with a fd which provdes the > + * handle to the allocated dma-buf > + * > + * Provided by userspace as an argument to the ioctl > + */ > +struct dma_heap_allocation_data { > + __u64 len; > + __u64 flags; > + __u32 fd; > + __u32 reserved0; > + __u32 reserved1; > + __u32 reserved2; > +}; > + > +#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.7.4 >
On 3/5/19 2:54 PM, John Stultz wrote: > 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: Greg KH <gregkh@linuxfoundation.org> > Cc: Sumit Semwal <sumit.semwal@linaro.org> > Cc: Liam Mark <lmark@codeaurora.org> > Cc: Brian Starkey <Brian.Starkey@arm.com> > Cc: Andrew F. Davis <afd@ti.com> > Cc: Chenbo Feng <fengc@google.com> > Cc: Alistair Strachan <astrachan@google.com> > Cc: dri-devel@lists.freedesktop.org > Signed-off-by: Andrew F. Davis <afd@ti.com> > [jstultz: reworded commit message, and lots of cleanups] > Signed-off-by: John Stultz <john.stultz@linaro.org> > --- > 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 then a buffer > (as it simplifies error handling) > --- > MAINTAINERS | 16 ++++ > drivers/dma-buf/Kconfig | 8 ++ > drivers/dma-buf/Makefile | 1 + > drivers/dma-buf/dma-heap.c | 191 ++++++++++++++++++++++++++++++++++++++++++ > include/linux/dma-heap.h | 65 ++++++++++++++ > include/uapi/linux/dma-heap.h | 52 ++++++++++++ > 6 files changed, 333 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 ac2e518..a661e19 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4621,6 +4621,22 @@ 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: Laura Abbott <labbott@redhat.com> > +R: Liam Mark <lmark@codeaurora.org> > +R: Brian Starkey <Brian.Starkey@arm.com> > +R: "Andrew F. Davis" <afd@ti.com> Quotes not needed in maintainers file. > +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 2e5a0fa..09c61db 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 0913a6c..b0332f1 100644 > --- a/drivers/dma-buf/Makefile > +++ b/drivers/dma-buf/Makefile > @@ -1,4 +1,5 @@ > obj-y := dma-buf.o dma-fence.o dma-fence-array.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 0000000..14b3975 > --- /dev/null > +++ b/drivers/dma-buf/dma-heap.c > @@ -0,0 +1,191 @@ > +// 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/idr.h> > +#include <linux/list.h> > +#include <linux/slab.h> > +#include <linux/uaccess.h> > + > +#include <linux/dma-heap.h> > +#include <uapi/linux/dma-heap.h> > + > +#define DEVNAME "dma_heap" > + > +#define NUM_HEAP_MINORS 128 > +static DEFINE_IDR(dma_heap_idr); > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ > + > +dev_t dma_heap_devt; > +struct class *dma_heap_class; > +struct list_head dma_heap_list; > +struct dentry *dma_heap_debug_root; > + > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > + unsigned int flags) > +{ > + len = PAGE_ALIGN(len); > + if (!len) > + return -EINVAL; > + > + return heap->ops->allocate(heap, len, flags); > +} > + > +static int dma_heap_open(struct inode *inode, struct file *filp) > +{ > + struct dma_heap *heap; > + > + mutex_lock(&minor_lock); > + heap = idr_find(&dma_heap_idr, iminor(inode)); > + mutex_unlock(&minor_lock); > + if (!heap) { > + pr_err("dma_heap: minor %d unknown.\n", iminor(inode)); > + return -ENODEV; > + } > + > + /* instance data as context */ > + filp->private_data = heap; > + nonseekable_open(inode, filp); > + > + return 0; > +} > + > +static int dma_heap_release(struct inode *inode, struct file *filp) > +{ > + filp->private_data = NULL; > + > + return 0; > +} > + > +static long dma_heap_ioctl(struct file *filp, unsigned int cmd, > + unsigned long arg) > +{ > + switch (cmd) { > + case DMA_HEAP_IOC_ALLOC: > + { > + struct dma_heap_allocation_data heap_allocation; > + struct dma_heap *heap = filp->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 || > + heap_allocation.reserved2) { Seems too many reserved, I can understand one, but if we ever needed all of these we would be better off just adding another alloc ioctl. > + pr_warn_once("dma_heap: ioctl data not valid\n"); > + return -EINVAL; > + } > + if (heap_allocation.flags & ~DMA_HEAP_VALID_FLAGS) { > + pr_warn_once("dma_heap: flags has invalid or unsupported flags set\n"); > + return -EINVAL; > + } > + > + fd = dma_heap_buffer_alloc(heap, heap_allocation.len, > + heap_allocation.flags); > + if (fd < 0) > + return fd; > + > + heap_allocation.fd = fd; > + > + if (copy_to_user((void __user *)arg, &heap_allocation, > + sizeof(heap_allocation))) > + return -EFAULT; > + > + break; > + } > + default: > + return -ENOTTY; > + } > + > + return 0; > +} > + > +static const struct file_operations dma_heap_fops = { > + .owner = THIS_MODULE, > + .open = dma_heap_open, > + .release = dma_heap_release, > + .unlocked_ioctl = dma_heap_ioctl, > +#ifdef CONFIG_COMPAT > + .compat_ioctl = dma_heap_ioctl, > +#endif > +}; > + > +int dma_heap_add(struct dma_heap *heap) > +{ > + struct device *dev_ret; > + int ret; > + > + if (!heap->name || !strcmp(heap->name, "")) { > + pr_err("dma_heap: Cannot add heap without a name\n"); As these names end up as the dev name in the file system we may want to check for invalid names, there is probably a helper for that somewhere. > + return -EINVAL; > + } > + > + if (!heap->ops || !heap->ops->allocate) { > + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); > + return -EINVAL; > + } > + > + /* Find unused minor number */ > + mutex_lock(&minor_lock); > + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); > + mutex_unlock(&minor_lock); > + if (ret < 0) { > + pr_err("dma_heap: Unable to get minor number for heap\n"); > + return ret; > + } > + heap->minor = ret; > + > + /* Create device */ > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > + 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 char device\n"); > + return PTR_ERR(dev_ret); > + } > + > + /* Add device */ > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > + if (ret < 0) { > + device_destroy(dma_heap_class, heap->heap_devt); > + pr_err("dma_heap: Unable to add char device\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(dma_heap_add); > + > +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); > + } > + > + 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 0000000..ed86a8e > --- /dev/null > +++ b/include/linux/dma-heap.h > @@ -0,0 +1,65 @@ > +/* 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_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 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; > + unsigned int minor; > + dev_t heap_devt; > + struct cdev heap_cdev; > +}; Still not sure about this, all of the members in this struct are strictly internally used by the framework. The users of this framework should not have access to them and only need to deal with an opaque pointer for tracking themselves (can store it in a private struct of their own then container_of to get back out their struct). Anyway, not a big deal, and if it really bugs me enough I can always go fix it later, it's all kernel internal so not a blocker here. :) Andrew > + > +/** > + * 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 flags); > +}; > + > +/** > + * dma_heap_add - adds a heap to dmabuf heaps > + * @heap: the heap to add > + */ > +int dma_heap_add(struct dma_heap *heap); > + > +#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 0000000..75c5d3f > --- /dev/null > +++ b/include/uapi/linux/dma-heap.h > @@ -0,0 +1,52 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * 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 > + * > + */ > + > +/* Currently no flags */ > +#define DMA_HEAP_VALID_FLAGS (0) > + > +/** > + * struct dma_heap_allocation_data - metadata passed from userspace for > + * allocations > + * @len: size of the allocation > + * @flags: flags passed to pool > + * @fd: will be populated with a fd which provdes the > + * handle to the allocated dma-buf > + * > + * Provided by userspace as an argument to the ioctl > + */ > +struct dma_heap_allocation_data { > + __u64 len; > + __u64 flags; > + __u32 fd; > + __u32 reserved0; > + __u32 reserved1; > + __u32 reserved2; > +}; > + > +#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 */ >
On Wed, Mar 6, 2019 at 8:12 AM Benjamin Gaignard <benjamin.gaignard@linaro.org> wrote: > Le mar. 5 mars 2019 à 21:54, John Stultz <john.stultz@linaro.org> a écrit : > > +/** > > + * DOC: DMABUF Heaps Userspace API > > + * > > + */ > > + > > +/* Currently no flags */ > > +#define DMA_HEAP_VALID_FLAGS (0) > > I think here you need to allow flags like O_RDWR or O_CLOEXEC else > mmap will fail. > Hm. So I meant for these to be just the bitmask of valid flags for the allocate IOCTL (used to make sure no one is passing junk flags accidentally), rather then valid flags for the heap open call. But this probably suggests I should call it something like DMA_HEAP_ALLOC_VALID_FLAGS instead? thanks -john
On Wed, Mar 6, 2019 at 10:18 AM Andrew F. Davis <afd@ti.com> wrote: > > On 3/5/19 2:54 PM, John Stultz wrote: > > 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: Greg KH <gregkh@linuxfoundation.org> > > Cc: Sumit Semwal <sumit.semwal@linaro.org> > > Cc: Liam Mark <lmark@codeaurora.org> > > Cc: Brian Starkey <Brian.Starkey@arm.com> > > Cc: Andrew F. Davis <afd@ti.com> > > Cc: Chenbo Feng <fengc@google.com> > > Cc: Alistair Strachan <astrachan@google.com> > > Cc: dri-devel@lists.freedesktop.org > > Signed-off-by: Andrew F. Davis <afd@ti.com> > > [jstultz: reworded commit message, and lots of cleanups] > > Signed-off-by: John Stultz <john.stultz@linaro.org> > > --- > > 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 then a buffer > > (as it simplifies error handling) > > --- > > MAINTAINERS | 16 ++++ > > drivers/dma-buf/Kconfig | 8 ++ > > drivers/dma-buf/Makefile | 1 + > > drivers/dma-buf/dma-heap.c | 191 ++++++++++++++++++++++++++++++++++++++++++ > > include/linux/dma-heap.h | 65 ++++++++++++++ > > include/uapi/linux/dma-heap.h | 52 ++++++++++++ > > 6 files changed, 333 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 ac2e518..a661e19 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -4621,6 +4621,22 @@ 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: Laura Abbott <labbott@redhat.com> > > +R: Liam Mark <lmark@codeaurora.org> > > +R: Brian Starkey <Brian.Starkey@arm.com> > > +R: "Andrew F. Davis" <afd@ti.com> > > Quotes not needed in maintainers file. Whatever you say, "Andrew F. Davis", or whomever you really are! ;) > > + > > + if (heap_allocation.fd || > > + heap_allocation.reserved0 || > > + heap_allocation.reserved1 || > > + heap_allocation.reserved2) { > > Seems too many reserved, I can understand one, but if we ever needed all > of these we would be better off just adding another alloc ioctl. Well, we have to have one u32 for padding. And I figured if we needed anything more then a u32, then we're in for 2 more. And I think the potential of the alignment and heap-private flags, I worry we might want to have something, but I guess we could just add a new ioctl and keep the support for the old one if folks prefer. > > +int dma_heap_add(struct dma_heap *heap) > > +{ > > + struct device *dev_ret; > > + int ret; > > + > > + if (!heap->name || !strcmp(heap->name, "")) { > > + pr_err("dma_heap: Cannot add heap without a name\n"); > > As these names end up as the dev name in the file system we may want to > check for invalid names, there is probably a helper for that somewhere. Hrm. I'll have to look. > > +struct dma_heap { > > + const char *name; > > + struct dma_heap_ops *ops; > > + unsigned int minor; > > + dev_t heap_devt; > > + struct cdev heap_cdev; > > +}; > > Still not sure about this, all of the members in this struct are > strictly internally used by the framework. The users of this framework > should not have access to them and only need to deal with an opaque > pointer for tracking themselves (can store it in a private struct of > their own then container_of to get back out their struct). > > Anyway, not a big deal, and if it really bugs me enough I can always go > fix it later, it's all kernel internal so not a blocker here. :) I guess I'd just move the include/linux/dma-heap.h to drivers/dma-buf/heaps/ and keep it localized there. But whichever. Feel free to also send a patch and I can fold it down. thanks -john
On 3/6/19 1:03 PM, John Stultz wrote: > On Wed, Mar 6, 2019 at 10:18 AM Andrew F. Davis <afd@ti.com> wrote: >> >> On 3/5/19 2:54 PM, John Stultz wrote: >>> 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: Greg KH <gregkh@linuxfoundation.org> >>> Cc: Sumit Semwal <sumit.semwal@linaro.org> >>> Cc: Liam Mark <lmark@codeaurora.org> >>> Cc: Brian Starkey <Brian.Starkey@arm.com> >>> Cc: Andrew F. Davis <afd@ti.com> >>> Cc: Chenbo Feng <fengc@google.com> >>> Cc: Alistair Strachan <astrachan@google.com> >>> Cc: dri-devel@lists.freedesktop.org >>> Signed-off-by: Andrew F. Davis <afd@ti.com> >>> [jstultz: reworded commit message, and lots of cleanups] >>> Signed-off-by: John Stultz <john.stultz@linaro.org> >>> --- >>> 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 then a buffer >>> (as it simplifies error handling) >>> --- >>> MAINTAINERS | 16 ++++ >>> drivers/dma-buf/Kconfig | 8 ++ >>> drivers/dma-buf/Makefile | 1 + >>> drivers/dma-buf/dma-heap.c | 191 ++++++++++++++++++++++++++++++++++++++++++ >>> include/linux/dma-heap.h | 65 ++++++++++++++ >>> include/uapi/linux/dma-heap.h | 52 ++++++++++++ >>> 6 files changed, 333 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 ac2e518..a661e19 100644 >>> --- a/MAINTAINERS >>> +++ b/MAINTAINERS >>> @@ -4621,6 +4621,22 @@ 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: Laura Abbott <labbott@redhat.com> >>> +R: Liam Mark <lmark@codeaurora.org> >>> +R: Brian Starkey <Brian.Starkey@arm.com> >>> +R: "Andrew F. Davis" <afd@ti.com> >> >> Quotes not needed in maintainers file. > > Whatever you say, "Andrew F. Davis", or whomever you really are! ;) > <_< >_> > >>> + >>> + if (heap_allocation.fd || >>> + heap_allocation.reserved0 || >>> + heap_allocation.reserved1 || >>> + heap_allocation.reserved2) { >> >> Seems too many reserved, I can understand one, but if we ever needed all >> of these we would be better off just adding another alloc ioctl. > > Well, we have to have one u32 for padding. And I figured if we needed > anything more then a u32, then we're in for 2 more. > > And I think the potential of the alignment and heap-private flags, I > worry we might want to have something, but I guess we could just add > a new ioctl and keep the support for the old one if folks prefer. > >>> +int dma_heap_add(struct dma_heap *heap) >>> +{ >>> + struct device *dev_ret; >>> + int ret; >>> + >>> + if (!heap->name || !strcmp(heap->name, "")) { >>> + pr_err("dma_heap: Cannot add heap without a name\n"); >> >> As these names end up as the dev name in the file system we may want to >> check for invalid names, there is probably a helper for that somewhere. > > Hrm. I'll have to look. > >>> +struct dma_heap { >>> + const char *name; >>> + struct dma_heap_ops *ops; >>> + unsigned int minor; >>> + dev_t heap_devt; >>> + struct cdev heap_cdev; >>> +}; >> >> Still not sure about this, all of the members in this struct are >> strictly internally used by the framework. The users of this framework >> should not have access to them and only need to deal with an opaque >> pointer for tracking themselves (can store it in a private struct of >> their own then container_of to get back out their struct). >> >> Anyway, not a big deal, and if it really bugs me enough I can always go >> fix it later, it's all kernel internal so not a blocker here. :) > > I guess I'd just move the include/linux/dma-heap.h to > drivers/dma-buf/heaps/ and keep it localized there. > But whichever. Feel free to also send a patch and I can fold it down. > The dma-heap.h needs to stay where it is, I was thinking just move struct dma_heap to inside drivers/dma-buf/dma-heap.c. I wouldn't worry about changing anything right now though, I'll post a patch you can squash in later one we confirm this whole dma-heap thing will get deemed acceptable in the first place. Thanks, Andrew > thanks > -john >
On 3/5/19 12:54 PM, John Stultz wrote: > +DMA-BUF HEAPS FRAMEWORK > +M: Laura Abbott<labbott@redhat.com> > +R: Liam Mark<lmark@codeaurora.org> > +R: Brian Starkey<Brian.Starkey@arm.com> > +R: "Andrew F. Davis"<afd@ti.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 So I talked about this with Sumit privately but I think it might make sense to have me step down as maintainer when this goes out of staging. I mostly worked on Ion at my previous position and anything I do now is mostly a side project. I still want to see it succeed which is why I took on the maintainer role but I don't want to become blocking for people who have a stronger vision about where this needs to go (see also, I'm not working with this on a daily basis). If you just want someone to help review or take patches to be pulled, I'm happy to do so but I'd hate to become the bottleneck on getting things done for people who are attempting to do real work. Thanks, Laura
On 3/15/19 3:54 AM, Christoph Hellwig wrote: >> +static int dma_heap_release(struct inode *inode, struct file *filp) >> +{ >> + filp->private_data = NULL; >> + >> + return 0; >> +} > > No point in clearing ->private_data, the file is about to be freed. > This was leftover from when release had some memory to free, will remove. >> + >> +static long dma_heap_ioctl(struct file *filp, unsigned int cmd, >> + unsigned long arg) > > Pleae don't use the weird legacy filp naming, file is a perfectly > valid and readable default name for struct file pointers. > Thanks for info, I saw both used and this was used where I found the prototype so I used it too, will fix. >> +{ >> + switch (cmd) { >> + case DMA_HEAP_IOC_ALLOC: >> + { >> + struct dma_heap_allocation_data heap_allocation; >> + struct dma_heap *heap = filp->private_data; >> + int fd; > > Please split each ioctl into a separate function from the very start, > otherwise this will grow into a spaghetty mess sooner than you can > see cheese. > Good idea, will fix. >> + dev_ret = device_create(dma_heap_class, >> + NULL, >> + heap->heap_devt, >> + NULL, >> + heap->name); > > No need this weird argument alignment. > I kinda like it this way, if everything cant fit on one line then everything gets its own line, seems more consistent. If there is strong objection I can fix.
On 3/15/19 3:18 PM, Laura Abbott wrote: > On 3/5/19 12:54 PM, John Stultz wrote: >> +DMA-BUF HEAPS FRAMEWORK >> +M: Laura Abbott<labbott@redhat.com> >> +R: Liam Mark<lmark@codeaurora.org> >> +R: Brian Starkey<Brian.Starkey@arm.com> >> +R: "Andrew F. Davis"<afd@ti.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 > > So I talked about this with Sumit privately but I think > it might make sense to have me step down as maintainer when > this goes out of staging. I mostly worked on Ion at my > previous position and anything I do now is mostly a side > project. I still want to see it succeed which is why I > took on the maintainer role but I don't want to become blocking > for people who have a stronger vision about where this needs > to go (see also, I'm not working with this on a daily basis). > > If you just want someone to help review or take patches > to be pulled, I'm happy to do so but I'd hate to become > the bottleneck on getting things done for people who > are attempting to do real work. > We could consider this as an "ION inspired" framework, and treat it like an extension of DMA-BUF. In which case Sumit could become the default Maintainer if he's up for it. Andrew > Thanks, > Laura
On Fri, Mar 15, 2019 at 1:18 PM Laura Abbott <labbott@redhat.com> wrote: > > On 3/5/19 12:54 PM, John Stultz wrote: > > +DMA-BUF HEAPS FRAMEWORK > > +M: Laura Abbott<labbott@redhat.com> > > +R: Liam Mark<lmark@codeaurora.org> > > +R: Brian Starkey<Brian.Starkey@arm.com> > > +R: "Andrew F. Davis"<afd@ti.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 > > So I talked about this with Sumit privately but I think > it might make sense to have me step down as maintainer when > this goes out of staging. I mostly worked on Ion at my > previous position and anything I do now is mostly a side > project. I still want to see it succeed which is why I > took on the maintainer role but I don't want to become blocking > for people who have a stronger vision about where this needs > to go (see also, I'm not working with this on a daily basis). > > If you just want someone to help review or take patches > to be pulled, I'm happy to do so but I'd hate to become > the bottleneck on getting things done for people who > are attempting to do real work. I worry this will make everyone to touch the side of their nose and yell "NOT IT!" :) First of all, thank you so much for your efforts maintaining ION along with your attempts to drag out requirements from interested parties and the numerous attempts to get collaborative discussion going at countless conferences! Your persistence and continual nudging in the face of apathetic private users of the code probably cannot be appreciated enough! Your past practical experience with ION and active work with the upstream community made you a stand out pick for this, but I understand not wanting to be eternally stuck with a maintainership if your not active in the area. I'm happy to volunteer as a neutral party, but I worry my limited experience with some of the more complicated usage would make my opinions less informed then they probably need to be. Further, as a neutral party, Sumit would probably be a better pick since he's already maintaining the dmabuf core. So I'd nominate Andrew, Liam or Benjamin (or all three?) as they all have more practical experience enabling past ION heaps on real devices and have demonstrated active interest in working in the community. So, in other words... NOT IT! :) -john
On 3/15/19 2:29 PM, John Stultz wrote: > On Fri, Mar 15, 2019 at 1:18 PM Laura Abbott <labbott@redhat.com> wrote: >> >> On 3/5/19 12:54 PM, John Stultz wrote: >>> +DMA-BUF HEAPS FRAMEWORK >>> +M: Laura Abbott<labbott@redhat.com> >>> +R: Liam Mark<lmark@codeaurora.org> >>> +R: Brian Starkey<Brian.Starkey@arm.com> >>> +R: "Andrew F. Davis"<afd@ti.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 >> >> So I talked about this with Sumit privately but I think >> it might make sense to have me step down as maintainer when >> this goes out of staging. I mostly worked on Ion at my >> previous position and anything I do now is mostly a side >> project. I still want to see it succeed which is why I >> took on the maintainer role but I don't want to become blocking >> for people who have a stronger vision about where this needs >> to go (see also, I'm not working with this on a daily basis). >> >> If you just want someone to help review or take patches >> to be pulled, I'm happy to do so but I'd hate to become >> the bottleneck on getting things done for people who >> are attempting to do real work. > > I worry this will make everyone to touch the side of their nose and > yell "NOT IT!" :) > > First of all, thank you so much for your efforts maintaining ION along > with your attempts to drag out requirements from interested parties > and the numerous attempts to get collaborative discussion going at > countless conferences! Your persistence and continual nudging in the > face of apathetic private users of the code probably cannot be > appreciated enough! > > Your past practical experience with ION and active work with the > upstream community made you a stand out pick for this, but I > understand not wanting to be eternally stuck with a maintainership if > your not active in the area. I'm happy to volunteer as a neutral > party, but I worry my limited experience with some of the more > complicated usage would make my opinions less informed then they > probably need to be. Further, as a neutral party, Sumit would > probably be a better pick since he's already maintaining the dmabuf > core. > Honestly if you're doing the work to re-write everything, I think you're more than qualified to be the maintainer. I would also support Sumit as well. > So I'd nominate Andrew, Liam or Benjamin (or all three?) as they all > have more practical experience enabling past ION heaps on real devices > and have demonstrated active interest in working in the community. > I do think this would benefit both from multiple maintainers and from maintainers who are actively using the framework. Like I said, I can still be a maintainer but I think having some comaintainers would be very helpful (and I'd support any of the names you've suggested) > So, in other words... NOT IT! :) I think you have to shout "Noes goes" first. :) > -john > Thanks, Laura P.S. For the benefit of anyone who's confused, https://en.wikipedia.org/wiki/Nose_goes
On Sat, 16 Mar 2019 at 04:15, Laura Abbott <labbott@redhat.com> wrote: > On 3/15/19 2:29 PM, John Stultz wrote: > > On Fri, Mar 15, 2019 at 1:18 PM Laura Abbott <labbott@redhat.com> wrote: > >> > >> On 3/5/19 12:54 PM, John Stultz wrote: > >>> +DMA-BUF HEAPS FRAMEWORK > >>> +M: Laura Abbott<labbott@redhat.com> > >>> +R: Liam Mark<lmark@codeaurora.org> > >>> +R: Brian Starkey<Brian.Starkey@arm.com> > >>> +R: "Andrew F. Davis"<afd@ti.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 > >> > >> So I talked about this with Sumit privately but I think > >> it might make sense to have me step down as maintainer when > >> this goes out of staging. I mostly worked on Ion at my > >> previous position and anything I do now is mostly a side > >> project. I still want to see it succeed which is why I > >> took on the maintainer role but I don't want to become blocking > >> for people who have a stronger vision about where this needs > >> to go (see also, I'm not working with this on a daily basis). > >> > >> If you just want someone to help review or take patches > >> to be pulled, I'm happy to do so but I'd hate to become > >> the bottleneck on getting things done for people who > >> are attempting to do real work. > > > > I worry this will make everyone to touch the side of their nose and > > yell "NOT IT!" :) > > > > First of all, thank you so much for your efforts maintaining ION along > > with your attempts to drag out requirements from interested parties > > and the numerous attempts to get collaborative discussion going at > > countless conferences! Your persistence and continual nudging in the > > face of apathetic private users of the code probably cannot be > > appreciated enough! > I totally second John here - the persistence has been inspiring to me personally as well :) > > > > Your past practical experience with ION and active work with the > > upstream community made you a stand out pick for this, but I > > understand not wanting to be eternally stuck with a maintainership if > > your not active in the area. I'm happy to volunteer as a neutral > > party, but I worry my limited experience with some of the more > > complicated usage would make my opinions less informed then they > > probably need to be. Further, as a neutral party, Sumit would > > probably be a better pick since he's already maintaining the dmabuf > > core. > > > > Honestly if you're doing the work to re-write everything, I > think you're more than qualified to be the maintainer. I > would also support Sumit as well. > + 1 > > So I'd nominate Andrew, Liam or Benjamin (or all three?) as they all > > have more practical experience enabling past ION heaps on real devices > > and have demonstrated active interest in working in the community. > > > > I do think this would benefit both from multiple maintainers and > from maintainers who are actively using the framework. Like I > said, I can still be a maintainer but I think having some comaintainers > would be very helpful (and I'd support any of the names you've > suggested) > If it's required, I am happy to co-maintain - we could even follow the drm-misc model of multiple co-maintainers. I will support any or all of the names above as well :) > > > So, in other words... NOT IT! :) > > I think you have to shout "Noes goes" first. :) > > > -john > > > > Thanks, > Laura > > P.S. For the benefit of anyone who's confused, > https://en.wikipedia.org/wiki/Nose_goes > Best, Sumit. <div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, 16 Mar 2019 at 04:15, Laura Abbott <<a href="mailto:labbott@redhat.com">labbott@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 3/15/19 2:29 PM, John Stultz wrote:<br> > On Fri, Mar 15, 2019 at 1:18 PM Laura Abbott <<a href="mailto:labbott@redhat.com" target="_blank">labbott@redhat.com</a>> wrote:<br> >><br> >> On 3/5/19 12:54 PM, John Stultz wrote:<br> >>> +DMA-BUF HEAPS FRAMEWORK<br> >>> +M: Laura Abbott<<a href="mailto:labbott@redhat.com" target="_blank">labbott@redhat.com</a>><br> >>> +R: Liam Mark<<a href="mailto:lmark@codeaurora.org" target="_blank">lmark@codeaurora.org</a>><br> >>> +R: Brian Starkey<<a href="mailto:Brian.Starkey@arm.com" target="_blank">Brian.Starkey@arm.com</a>><br> >>> +R: "Andrew F. Davis"<<a href="mailto:afd@ti.com" target="_blank">afd@ti.com</a>><br> >>> +R: John Stultz<<a href="mailto:john.stultz@linaro.org" target="_blank">john.stultz@linaro.org</a>><br> >>> +S: Maintained<br> >>> +L: <a href="mailto:linux-media@vger.kernel.org" target="_blank">linux-media@vger.kernel.org</a><br> >>> +L: <a href="mailto:dri-devel@lists.freedesktop.org" target="_blank">dri-devel@lists.freedesktop.org</a><br> >>> +L: <a href="mailto:linaro-mm-sig@lists.linaro.org" target="_blank">linaro-mm-sig@lists.linaro.org</a> (moderated for non-subscribers)<br> >>> +F: include/uapi/linux/dma-heap.h<br> >>> +F: include/linux/dma-heap.h<br> >>> +F: drivers/dma-buf/dma-heap.c<br> >>> +F: drivers/dma-buf/heaps/*<br> >>> +T: git git://<a href="http://anongit.freedesktop.org/drm/drm-misc" rel="noreferrer" target="_blank">anongit.freedesktop.org/drm/drm-misc</a><br> >><br> >> So I talked about this with Sumit privately but I think<br> >> it might make sense to have me step down as maintainer when<br> >> this goes out of staging. I mostly worked on Ion at my<br> >> previous position and anything I do now is mostly a side<br> >> project. I still want to see it succeed which is why I<br> >> took on the maintainer role but I don't want to become blocking<br> >> for people who have a stronger vision about where this needs<br> >> to go (see also, I'm not working with this on a daily basis).<br> >><br> >> If you just want someone to help review or take patches<br> >> to be pulled, I'm happy to do so but I'd hate to become<br> >> the bottleneck on getting things done for people who<br> >> are attempting to do real work.<br> > <br> > I worry this will make everyone to touch the side of their nose and<br> > yell "NOT IT!" :)<br> > <br> > First of all, thank you so much for your efforts maintaining ION along<br> > with your attempts to drag out requirements from interested parties<br> > and the numerous attempts to get collaborative discussion going at<br> > countless conferences! Your persistence and continual nudging in the<br> > face of apathetic private users of the code probably cannot be<br> > appreciated enough!<br></blockquote><div>I totally second John here - the persistence has been inspiring to me personally as well :) </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> > <br> > Your past practical experience with ION and active work with the<br> > upstream community made you a stand out pick for this, but I<br> > understand not wanting to be eternally stuck with a maintainership if<br> > your not active in the area. I'm happy to volunteer as a neutral<br> > party, but I worry my limited experience with some of the more<br> > complicated usage would make my opinions less informed then they<br> > probably need to be. Further, as a neutral party, Sumit would<br> > probably be a better pick since he's already maintaining the dmabuf<br> > core.<br> > <br> <br> Honestly if you're doing the work to re-write everything, I<br> think you're more than qualified to be the maintainer. I<br> would also support Sumit as well.<br> + 1<br> > So I'd nominate Andrew, Liam or Benjamin (or all three?) as they all<br> > have more practical experience enabling past ION heaps on real devices<br> > and have demonstrated active interest in working in the community.<br> > <br> <br> I do think this would benefit both from multiple maintainers and<br> from maintainers who are actively using the framework. Like I<br> said, I can still be a maintainer but I think having some comaintainers<br> would be very helpful (and I'd support any of the names you've<br> suggested)<br></blockquote><div><br></div><div>If it's required, I am happy to co-maintain - we could even follow the drm-misc model of multiple co-maintainers. I will support any or all of the names above as well :) </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br> > So, in other words... NOT IT! :)<br> <br> I think you have to shout "Noes goes" first. :)<br> <br> > -john<br> > <br> <br> Thanks,<br> Laura<br> <br> P.S. For the benefit of anyone who's confused,<br> <a href="https://en.wikipedia.org/wiki/Nose_goes" rel="noreferrer" target="_blank">https://en.wikipedia.org/wiki/Nose_goes</a><br> </blockquote></div><br><div>Best,</div><div>Sumit.</div></div>
On Sat, 16 Mar 2019 at 04:15, Laura Abbott <labbott@redhat.com> wrote: > > On 3/15/19 2:29 PM, John Stultz wrote: > > On Fri, Mar 15, 2019 at 1:18 PM Laura Abbott <labbott@redhat.com> wrote: > >> > >> On 3/5/19 12:54 PM, John Stultz wrote: > >>> +DMA-BUF HEAPS FRAMEWORK > >>> +M: Laura Abbott<labbott@redhat.com> > >>> +R: Liam Mark<lmark@codeaurora.org> > >>> +R: Brian Starkey<Brian.Starkey@arm.com> > >>> +R: "Andrew F. Davis"<afd@ti.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 > >> > >> So I talked about this with Sumit privately but I think > >> it might make sense to have me step down as maintainer when > >> this goes out of staging. I mostly worked on Ion at my > >> previous position and anything I do now is mostly a side > >> project. I still want to see it succeed which is why I > >> took on the maintainer role but I don't want to become blocking > >> for people who have a stronger vision about where this needs > >> to go (see also, I'm not working with this on a daily basis). > >> > >> If you just want someone to help review or take patches > >> to be pulled, I'm happy to do so but I'd hate to become > >> the bottleneck on getting things done for people who > >> are attempting to do real work. > > > > I worry this will make everyone to touch the side of their nose and > > yell "NOT IT!" :) > > > > First of all, thank you so much for your efforts maintaining ION along > > with your attempts to drag out requirements from interested parties > > and the numerous attempts to get collaborative discussion going at > > countless conferences! Your persistence and continual nudging in the > > face of apathetic private users of the code probably cannot be > > appreciated enough! I totally second John here - the persistence has been inspiring to me personally as well :) > > > > Your past practical experience with ION and active work with the > > upstream community made you a stand out pick for this, but I > > understand not wanting to be eternally stuck with a maintainership if > > your not active in the area. I'm happy to volunteer as a neutral > > party, but I worry my limited experience with some of the more > > complicated usage would make my opinions less informed then they > > probably need to be. Further, as a neutral party, Sumit would > > probably be a better pick since he's already maintaining the dmabuf > > core. > > > > Honestly if you're doing the work to re-write everything, I > think you're more than qualified to be the maintainer. I > would also support Sumit as well. > > > So I'd nominate Andrew, Liam or Benjamin (or all three?) as they all > > have more practical experience enabling past ION heaps on real devices > > and have demonstrated active interest in working in the community. > > > > I do think this would benefit both from multiple maintainers and > from maintainers who are actively using the framework. Like I > said, I can still be a maintainer but I think having some comaintainers > would be very helpful (and I'd support any of the names you've > suggested) If it's required, I am happy to co-maintain - we could even follow the drm-misc model of multiple co-maintainers. I will support any or all of the names above as well :) > > > So, in other words... NOT IT! :) > > I think you have to shout "Noes goes" first. :) > > > -john > > > > Thanks, > Laura > > P.S. For the benefit of anyone who's confused, > https://en.wikipedia.org/wiki/Nose_goes Best, Sumit.
Hi John, On Tue, Mar 05, 2019 at 12:54:29PM -0800, John Stultz wrote: > From: "Andrew F. Davis" <afd@ti.com> [snip] > + > +#define NUM_HEAP_MINORS 128 > +static DEFINE_IDR(dma_heap_idr); > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ I saw that Matthew Wilcox is trying to nuke idr: https://patchwork.freedesktop.org/series/57073/ Perhaps a different data structure could be considered? (I don't have an informed opinion on which). > + > +dev_t dma_heap_devt; > +struct class *dma_heap_class; > +struct list_head dma_heap_list; > +struct dentry *dma_heap_debug_root; > + > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > + unsigned int flags) > +{ > + len = PAGE_ALIGN(len); > + if (!len) > + return -EINVAL; I think aligning len to pages only makes sense if heaps are going to allocate aligned to pages too. Perhaps that's an implicit assumption? If so, lets document it. Why not let the heaps take care of aligning len however they want though? ... > + > +int dma_heap_add(struct dma_heap *heap) > +{ > + struct device *dev_ret; > + int ret; > + > + if (!heap->name || !strcmp(heap->name, "")) { > + pr_err("dma_heap: Cannot add heap without a name\n"); > + return -EINVAL; > + } > + > + if (!heap->ops || !heap->ops->allocate) { > + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); > + return -EINVAL; > + } > + > + /* Find unused minor number */ > + mutex_lock(&minor_lock); > + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); > + mutex_unlock(&minor_lock); > + if (ret < 0) { > + pr_err("dma_heap: Unable to get minor number for heap\n"); > + return ret; > + } > + heap->minor = ret; > + > + /* Create device */ > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > + 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 char device\n"); > + return PTR_ERR(dev_ret); > + } > + > + /* Add device */ > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); Shouldn't this be s/dma_heap_devt/heap->heap_devt/ and a count of 1? Also would it be better to have cdev_add/device_create the other way around? First create the char device, then once it's all set up register it with sysfs. > + if (ret < 0) { > + device_destroy(dma_heap_class, heap->heap_devt); > + pr_err("dma_heap: Unable to add char device\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(dma_heap_add); Until we've figured out how modules are going to work, I still think it would be a good idea to not export this. Cheers, -Brian
On 3/19/19 7:08 AM, Brian Starkey wrote: > Hi John, > > On Tue, Mar 05, 2019 at 12:54:29PM -0800, John Stultz wrote: >> From: "Andrew F. Davis" <afd@ti.com> > > [snip] > >> + >> +#define NUM_HEAP_MINORS 128 >> +static DEFINE_IDR(dma_heap_idr); >> +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ > > I saw that Matthew Wilcox is trying to nuke idr: > https://patchwork.freedesktop.org/series/57073/ > > Perhaps a different data structure could be considered? (I don't have > an informed opinion on which). > Looks like XArray is the suggested replacement. Should be easy enough, the minor number would just index to our heap struct directly, I'll give it a shot and see. >> + >> +dev_t dma_heap_devt; >> +struct class *dma_heap_class; >> +struct list_head dma_heap_list; >> +struct dentry *dma_heap_debug_root; >> + >> +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, >> + unsigned int flags) >> +{ >> + len = PAGE_ALIGN(len); >> + if (!len) >> + return -EINVAL; > > I think aligning len to pages only makes sense if heaps are going to > allocate aligned to pages too. Perhaps that's an implicit assumption? > If so, lets document it. > > Why not let the heaps take care of aligning len however they want > though? > This is how I originally had it, but I think we couldn't find any case where you would want an the start or end of a buffer to not fall on a page boundary here. It would only lead to problems. As you say though, nothing keeping us from moving that into the heaps themselves. > ... > >> + >> +int dma_heap_add(struct dma_heap *heap) >> +{ >> + struct device *dev_ret; >> + int ret; >> + >> + if (!heap->name || !strcmp(heap->name, "")) { >> + pr_err("dma_heap: Cannot add heap without a name\n"); >> + return -EINVAL; >> + } >> + >> + if (!heap->ops || !heap->ops->allocate) { >> + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); >> + return -EINVAL; >> + } >> + >> + /* Find unused minor number */ >> + mutex_lock(&minor_lock); >> + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); >> + mutex_unlock(&minor_lock); >> + if (ret < 0) { >> + pr_err("dma_heap: Unable to get minor number for heap\n"); >> + return ret; >> + } >> + heap->minor = ret; >> + >> + /* Create device */ >> + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); >> + 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 char device\n"); >> + return PTR_ERR(dev_ret); >> + } >> + >> + /* Add device */ >> + cdev_init(&heap->heap_cdev, &dma_heap_fops); >> + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > > Shouldn't this be s/dma_heap_devt/heap->heap_devt/ and a count of 1? > Hmm, strange this ever worked before.. > Also would it be better to have cdev_add/device_create the other way > around? First create the char device, then once it's all set up > register it with sysfs. > Yes that does seem to be more common, lets flip it. >> + if (ret < 0) { >> + device_destroy(dma_heap_class, heap->heap_devt); >> + pr_err("dma_heap: Unable to add char device\n"); >> + return ret; >> + } >> + >> + return 0; >> +} >> +EXPORT_SYMBOL(dma_heap_add); > > Until we've figured out how modules are going to work, I still think > it would be a good idea to not export this. > Agree. Andrew > Cheers, > -Brian >
On Tue, Mar 19, 2019 at 5:08 AM Brian Starkey <Brian.Starkey@arm.com> wrote: > > Hi John, > > On Tue, Mar 05, 2019 at 12:54:29PM -0800, John Stultz wrote: > > From: "Andrew F. Davis" <afd@ti.com> > > [snip] > > > + > > +#define NUM_HEAP_MINORS 128 > > +static DEFINE_IDR(dma_heap_idr); > > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ > > I saw that Matthew Wilcox is trying to nuke idr: > https://patchwork.freedesktop.org/series/57073/ > > Perhaps a different data structure could be considered? (I don't have > an informed opinion on which). Thanks for pointing this out! I've just switched to using the Xarray implementation in my tree. > > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > > + unsigned int flags) > > +{ > > + len = PAGE_ALIGN(len); > > + if (!len) > > + return -EINVAL; > > I think aligning len to pages only makes sense if heaps are going to > allocate aligned to pages too. Perhaps that's an implicit assumption? > If so, lets document it. I've added a comment as such (or do you have more thoughts on where it should be documented?), and for consistency removed the PAGE_ALIGN usage in the heap allocator hooks. > Why not let the heaps take care of aligning len however they want > though? As Andrew already said, It seems page granularity would have to be the finest allocation granularity for dmabufs. If heaps want to implement their own larger granularity alignment, I don't see any reason they would be limited there. And for me, its mostly because I stubbed my toe implementing the heap code w/ the first patch that didn't have the page alignment in the generic code. :) > > + /* Create device */ > > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > > + 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 char device\n"); > > + return PTR_ERR(dev_ret); > > + } > > + > > + /* Add device */ > > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > > Shouldn't this be s/dma_heap_devt/heap->heap_devt/ and a count of 1? > > Also would it be better to have cdev_add/device_create the other way > around? First create the char device, then once it's all set up > register it with sysfs. Thanks for catching that! Much appreciated! Reworked as suggested. Though I realized last week I have not figured out a consistent way to have the heaps show up in /dev/dma_heaps/<device> on both Android and classic Linux environments. I need to go stare at the /dev/input/ setup code some more. > > + if (ret < 0) { > > + device_destroy(dma_heap_class, heap->heap_devt); > > + pr_err("dma_heap: Unable to add char device\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(dma_heap_add); > > Until we've figured out how modules are going to work, I still think > it would be a good idea to not export this. Done! thanks -john
On Tue, Mar 05, 2019 at 12:54:29PM -0800, John Stultz wrote: > 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! Comments just on the user/kernel api and how it interacts with the driver model. Not on the "real" functionality of this code :) > +#define DEVNAME "dma_heap" > + > +#define NUM_HEAP_MINORS 128 Why a max? > +static DEFINE_IDR(dma_heap_idr); > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ Move to use xarray now so that Matthew doesn't have to send patches converting this code later :) It also allows you to drop the mutex. > + > +dev_t dma_heap_devt; > +struct class *dma_heap_class; > +struct list_head dma_heap_list; > +struct dentry *dma_heap_debug_root; Global variables? > + > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > + unsigned int flags) > +{ > + len = PAGE_ALIGN(len); > + if (!len) > + return -EINVAL; > + > + return heap->ops->allocate(heap, len, flags); > +} > + > +static int dma_heap_open(struct inode *inode, struct file *filp) > +{ > + struct dma_heap *heap; > + > + mutex_lock(&minor_lock); > + heap = idr_find(&dma_heap_idr, iminor(inode)); > + mutex_unlock(&minor_lock); > + if (!heap) { > + pr_err("dma_heap: minor %d unknown.\n", iminor(inode)); > + return -ENODEV; > + } > + > + /* instance data as context */ > + filp->private_data = heap; > + nonseekable_open(inode, filp); > + > + return 0; > +} > + > +static int dma_heap_release(struct inode *inode, struct file *filp) > +{ > + filp->private_data = NULL; Why does this matter? release should only be called on the way out of here, no need to do anything as nothing else can be called, right? release shouldn't be needed from what I can tell. > + > + return 0; > +} > + > +static long dma_heap_ioctl(struct file *filp, unsigned int cmd, > + unsigned long arg) > +{ > + switch (cmd) { > + case DMA_HEAP_IOC_ALLOC: > + { > + struct dma_heap_allocation_data heap_allocation; > + struct dma_heap *heap = filp->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 || > + heap_allocation.reserved2) { > + pr_warn_once("dma_heap: ioctl data not valid\n"); > + return -EINVAL; > + } Good job in forcing the reserved fields to be 0! > + if (heap_allocation.flags & ~DMA_HEAP_VALID_FLAGS) { > + pr_warn_once("dma_heap: flags has invalid or unsupported flags set\n"); > + return -EINVAL; > + } > + > + fd = dma_heap_buffer_alloc(heap, heap_allocation.len, > + heap_allocation.flags); No max value checking for .len? Can you really ask for anything? > + if (fd < 0) > + return fd; > + > + heap_allocation.fd = fd; > + > + if (copy_to_user((void __user *)arg, &heap_allocation, > + sizeof(heap_allocation))) > + return -EFAULT; > + > + break; > + } > + default: > + return -ENOTTY; > + } > + > + return 0; > +} > + > +static const struct file_operations dma_heap_fops = { > + .owner = THIS_MODULE, > + .open = dma_heap_open, > + .release = dma_heap_release, > + .unlocked_ioctl = dma_heap_ioctl, > +#ifdef CONFIG_COMPAT > + .compat_ioctl = dma_heap_ioctl, > +#endif Why is compat_ioctl even needed? > +}; > + > +int dma_heap_add(struct dma_heap *heap) > +{ > + struct device *dev_ret; > + int ret; > + > + if (!heap->name || !strcmp(heap->name, "")) { > + pr_err("dma_heap: Cannot add heap without a name\n"); > + return -EINVAL; > + } > + > + if (!heap->ops || !heap->ops->allocate) { > + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); > + return -EINVAL; > + } > + > + /* Find unused minor number */ > + mutex_lock(&minor_lock); > + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); > + mutex_unlock(&minor_lock); Again, xarray. But I will ask you to back up, why need a major number at all? Why not just use the misc subsystem? How many of these are you going to have over time in a "normal" system? How about a "abnormal system"? We have seen people running Android in "containers" such that they needed binderfs to handle huge numbers of individual android systems running at the same time. Will this api break those systems if you have a tiny maximum number you an allocate? > + if (ret < 0) { > + pr_err("dma_heap: Unable to get minor number for heap\n"); > + return ret; > + } > + heap->minor = ret; > + > + /* Create device */ > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > + dev_ret = device_create(dma_heap_class, > + NULL, > + heap->heap_devt, > + NULL, > + heap->name); No parent? Can't hang this off of anything? Ok, having it show up in /sys/devices/virtual/ is probably good enough. > + if (IS_ERR(dev_ret)) { > + pr_err("dma_heap: Unable to create char device\n"); > + return PTR_ERR(dev_ret); > + } > + > + /* Add device */ > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > + if (ret < 0) { > + device_destroy(dma_heap_class, heap->heap_devt); > + pr_err("dma_heap: Unable to add char device\n"); > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(dma_heap_add); EXPORT_SYMBOL_GPL() please? For core stuff like this it's good. > + > +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); > + } > + > + return 0; > +} > +subsys_initcall(dma_heap_init); Overall, looks sane, the comments above are all really minor. > --- /dev/null > +++ b/include/uapi/linux/dma-heap.h > @@ -0,0 +1,52 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ Wrong license for a uapi .h file :( thanks, greg k-h
On Wed, Mar 27, 2019 at 11:25 AM Greg KH <gregkh@linuxfoundation.org> wrote: > > On Tue, Mar 05, 2019 at 12:54:29PM -0800, John Stultz wrote: > > 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! > > Comments just on the user/kernel api and how it interacts with the > driver model. Not on the "real" functionality of this code :) Thanks so much for the feedback! In some cases Andrew and I have already made the changes you've suggested, and hopefully will have a new version to share soon. > > +#define DEVNAME "dma_heap" > > + > > +#define NUM_HEAP_MINORS 128 > > Why a max? Mostly because other drivers do. I'll see if this can be removed with the Xarray bits. > > +static DEFINE_IDR(dma_heap_idr); > > +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ > > Move to use xarray now so that Matthew doesn't have to send patches > converting this code later :) > > It also allows you to drop the mutex. Yep. Already converted to Xarray, it is nicer! > > +dev_t dma_heap_devt; > > +struct class *dma_heap_class; > > +struct list_head dma_heap_list; > > +struct dentry *dma_heap_debug_root; > > Global variables? Oops. Will make those static. Thanks! > > + > > +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, > > + unsigned int flags) > > +{ > > + len = PAGE_ALIGN(len); > > + if (!len) > > + return -EINVAL; > > + > > + return heap->ops->allocate(heap, len, flags); > > +} > > + > > +static int dma_heap_open(struct inode *inode, struct file *filp) > > +{ > > + struct dma_heap *heap; > > + > > + mutex_lock(&minor_lock); > > + heap = idr_find(&dma_heap_idr, iminor(inode)); > > + mutex_unlock(&minor_lock); > > + if (!heap) { > > + pr_err("dma_heap: minor %d unknown.\n", iminor(inode)); > > + return -ENODEV; > > + } > > + > > + /* instance data as context */ > > + filp->private_data = heap; > > + nonseekable_open(inode, filp); > > + > > + return 0; > > +} > > + > > +static int dma_heap_release(struct inode *inode, struct file *filp) > > +{ > > + filp->private_data = NULL; > > Why does this matter? release should only be called on the way out of > here, no need to do anything as nothing else can be called, right? > > release shouldn't be needed from what I can tell. Yep. Christoph suggested the same and its been removed already. > > + if (heap_allocation.flags & ~DMA_HEAP_VALID_FLAGS) { > > + pr_warn_once("dma_heap: flags has invalid or unsupported flags set\n"); > > + return -EINVAL; > > + } > > + > > + fd = dma_heap_buffer_alloc(heap, heap_allocation.len, > > + heap_allocation.flags); > > No max value checking for .len? Can you really ask for anything? So I think any length caps would be heap specific, so we want to pass them on here. > > +static const struct file_operations dma_heap_fops = { > > + .owner = THIS_MODULE, > > + .open = dma_heap_open, > > + .release = dma_heap_release, > > + .unlocked_ioctl = dma_heap_ioctl, > > +#ifdef CONFIG_COMPAT > > + .compat_ioctl = dma_heap_ioctl, > > +#endif > > Why is compat_ioctl even needed? Probably my mistake. I didn't realize if we're running 32bit on 64bit and there's no compat, the unlocked_ioctl gets called. > > + /* Find unused minor number */ > > + mutex_lock(&minor_lock); > > + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); > > + mutex_unlock(&minor_lock); > > Again, xarray. Ack. > But I will ask you to back up, why need a major number at all? Why not > just use the misc subsystem? How many of these are you going to have > over time in a "normal" system? How about a "abnormal system"? So early implementations did use misc, but in order to get the /dev/heap/cma_heap style directories, in both Android and classic udev linux systems I had to create a class. This v2 patch didn't get it quite right (got it working properly in android but not on classic systems), but the next version does get the subdir created properly (similar to how the input layer does it). As for number of heaps, I wouldn't expect there to be a ton on any given system. Most likely less then 16, but possibly up to 32. 128 seemed like a safe "crazy out there" cap. But perspectives on crazy shift over time :) > We have seen people running Android in "containers" such that they > needed binderfs to handle huge numbers of individual android systems > running at the same time. Will this api break those systems if you have > a tiny maximum number you an allocate? I'd have to think some more on this. Right now I'd expect that you'd not be trying to virtualize the heaps in a container so you'd not have m heaps * n containers on the system. Instead the containers would mount/link in the devnode (I'm a bit fuzzy on how containers handle devnode creation/restrictions) as appropriate (the nice part with this over ION is we have per heap dev nodes, so the set shared can be limited). But I'd have to think more about the risks of how multiple containers might share things like cma heaps. > > + if (ret < 0) { > > + pr_err("dma_heap: Unable to get minor number for heap\n"); > > + return ret; > > + } > > + heap->minor = ret; > > + > > + /* Create device */ > > + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); > > + dev_ret = device_create(dma_heap_class, > > + NULL, > > + heap->heap_devt, > > + NULL, > > + heap->name); > > No parent? Can't hang this off of anything? Ok, having it show up in > /sys/devices/virtual/ is probably good enough. > > > + if (IS_ERR(dev_ret)) { > > + pr_err("dma_heap: Unable to create char device\n"); > > + return PTR_ERR(dev_ret); > > + } > > + > > + /* Add device */ > > + cdev_init(&heap->heap_cdev, &dma_heap_fops); > > + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); > > + if (ret < 0) { > > + device_destroy(dma_heap_class, heap->heap_devt); > > + pr_err("dma_heap: Unable to add char device\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(dma_heap_add); > > EXPORT_SYMBOL_GPL() please? For core stuff like this it's good. Actually, removed the export completely for now since its probably not ready for modules yet. But will be sure to tag it GPL when we do re-add it. > > + > > +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); > > + } > > + > > + return 0; > > +} > > +subsys_initcall(dma_heap_init); > > Overall, looks sane, the comments above are all really minor. Very much appreciate the review! > > > --- /dev/null > > +++ b/include/uapi/linux/dma-heap.h > > @@ -0,0 +1,52 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > Wrong license for a uapi .h file :( Ack. Fixed. Thanks so much again! -john
diff --git a/MAINTAINERS b/MAINTAINERS index ac2e518..a661e19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4621,6 +4621,22 @@ 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: Laura Abbott <labbott@redhat.com> +R: Liam Mark <lmark@codeaurora.org> +R: Brian Starkey <Brian.Starkey@arm.com> +R: "Andrew F. Davis" <afd@ti.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 2e5a0fa..09c61db 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 0913a6c..b0332f1 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,4 +1,5 @@ obj-y := dma-buf.o dma-fence.o dma-fence-array.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 0000000..14b3975 --- /dev/null +++ b/drivers/dma-buf/dma-heap.c @@ -0,0 +1,191 @@ +// 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/idr.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/uaccess.h> + +#include <linux/dma-heap.h> +#include <uapi/linux/dma-heap.h> + +#define DEVNAME "dma_heap" + +#define NUM_HEAP_MINORS 128 +static DEFINE_IDR(dma_heap_idr); +static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ + +dev_t dma_heap_devt; +struct class *dma_heap_class; +struct list_head dma_heap_list; +struct dentry *dma_heap_debug_root; + +static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, + unsigned int flags) +{ + len = PAGE_ALIGN(len); + if (!len) + return -EINVAL; + + return heap->ops->allocate(heap, len, flags); +} + +static int dma_heap_open(struct inode *inode, struct file *filp) +{ + struct dma_heap *heap; + + mutex_lock(&minor_lock); + heap = idr_find(&dma_heap_idr, iminor(inode)); + mutex_unlock(&minor_lock); + if (!heap) { + pr_err("dma_heap: minor %d unknown.\n", iminor(inode)); + return -ENODEV; + } + + /* instance data as context */ + filp->private_data = heap; + nonseekable_open(inode, filp); + + return 0; +} + +static int dma_heap_release(struct inode *inode, struct file *filp) +{ + filp->private_data = NULL; + + return 0; +} + +static long dma_heap_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + switch (cmd) { + case DMA_HEAP_IOC_ALLOC: + { + struct dma_heap_allocation_data heap_allocation; + struct dma_heap *heap = filp->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 || + heap_allocation.reserved2) { + pr_warn_once("dma_heap: ioctl data not valid\n"); + return -EINVAL; + } + if (heap_allocation.flags & ~DMA_HEAP_VALID_FLAGS) { + pr_warn_once("dma_heap: flags has invalid or unsupported flags set\n"); + return -EINVAL; + } + + fd = dma_heap_buffer_alloc(heap, heap_allocation.len, + heap_allocation.flags); + if (fd < 0) + return fd; + + heap_allocation.fd = fd; + + if (copy_to_user((void __user *)arg, &heap_allocation, + sizeof(heap_allocation))) + return -EFAULT; + + break; + } + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations dma_heap_fops = { + .owner = THIS_MODULE, + .open = dma_heap_open, + .release = dma_heap_release, + .unlocked_ioctl = dma_heap_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = dma_heap_ioctl, +#endif +}; + +int dma_heap_add(struct dma_heap *heap) +{ + struct device *dev_ret; + int ret; + + if (!heap->name || !strcmp(heap->name, "")) { + pr_err("dma_heap: Cannot add heap without a name\n"); + return -EINVAL; + } + + if (!heap->ops || !heap->ops->allocate) { + pr_err("dma_heap: Cannot add heap with invalid ops struct\n"); + return -EINVAL; + } + + /* Find unused minor number */ + mutex_lock(&minor_lock); + ret = idr_alloc(&dma_heap_idr, heap, 0, NUM_HEAP_MINORS, GFP_KERNEL); + mutex_unlock(&minor_lock); + if (ret < 0) { + pr_err("dma_heap: Unable to get minor number for heap\n"); + return ret; + } + heap->minor = ret; + + /* Create device */ + heap->heap_devt = MKDEV(MAJOR(dma_heap_devt), heap->minor); + 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 char device\n"); + return PTR_ERR(dev_ret); + } + + /* Add device */ + cdev_init(&heap->heap_cdev, &dma_heap_fops); + ret = cdev_add(&heap->heap_cdev, dma_heap_devt, NUM_HEAP_MINORS); + if (ret < 0) { + device_destroy(dma_heap_class, heap->heap_devt); + pr_err("dma_heap: Unable to add char device\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL(dma_heap_add); + +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); + } + + 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 0000000..ed86a8e --- /dev/null +++ b/include/linux/dma-heap.h @@ -0,0 +1,65 @@ +/* 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_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 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; + unsigned int minor; + dev_t heap_devt; + struct cdev heap_cdev; +}; + +/** + * 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 flags); +}; + +/** + * dma_heap_add - adds a heap to dmabuf heaps + * @heap: the heap to add + */ +int dma_heap_add(struct dma_heap *heap); + +#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 0000000..75c5d3f --- /dev/null +++ b/include/uapi/linux/dma-heap.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * 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 + * + */ + +/* Currently no flags */ +#define DMA_HEAP_VALID_FLAGS (0) + +/** + * struct dma_heap_allocation_data - metadata passed from userspace for + * allocations + * @len: size of the allocation + * @flags: flags passed to pool + * @fd: will be populated with a fd which provdes the + * handle to the allocated dma-buf + * + * Provided by userspace as an argument to the ioctl + */ +struct dma_heap_allocation_data { + __u64 len; + __u64 flags; + __u32 fd; + __u32 reserved0; + __u32 reserved1; + __u32 reserved2; +}; + +#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 */