All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel@ffwll.ch>
To: "Noralf Trønnes" <noralf@tronnes.org>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [RFC 3/6] dma-buf: Support generic userspace allocations
Date: Wed, 4 Jan 2017 16:08:55 +0100	[thread overview]
Message-ID: <20170104150855.23lu5hfzk6ciagln@phenom.ffwll.local> (raw)
In-Reply-To: <20170104133442.4534-4-noralf@tronnes.org>

On Wed, Jan 04, 2017 at 02:34:39PM +0100, Noralf Trønnes wrote:
> Add a generic way for userspace to allocate dma-buf's for SPI transfers.
> 
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

Having a central dma-buf allocator is a common thing, there's already ION
in drivers/staging/android. If we need one I think it's better to
accelarate ION destaging than creating yet another one.
> ---
>  drivers/dma-buf/Makefile         |   2 +-
>  drivers/dma-buf/dev.c            | 211 +++++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/dma-buf-dev.h |  35 +++++++
>  3 files changed, 247 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/dma-buf/dev.c
>  create mode 100644 include/uapi/linux/dma-buf-dev.h
> 
> diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> index 210a10b..ec867f7 100644
> --- a/drivers/dma-buf/Makefile
> +++ b/drivers/dma-buf/Makefile
> @@ -1,3 +1,3 @@
> -obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o
> +obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o dev.o
>  obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
>  obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.o
> diff --git a/drivers/dma-buf/dev.c b/drivers/dma-buf/dev.c
> new file mode 100644
> index 0000000..536d9bf
> --- /dev/null
> +++ b/drivers/dma-buf/dev.c
> @@ -0,0 +1,211 @@
> +/*
> + * Copyright (C) 2016 Noralf Trønnes
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/dma-buf.h>
> +#include <linux/miscdevice.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <uapi/linux/dma-buf-dev.h>
> +
> +struct dma_buf_dev_object {
> +	struct device *dev;
> +	unsigned long attrs;
> +	dma_addr_t dma_addr;
> +	void *vaddr;
> +	size_t size;
> +};
> +
> +static struct sg_table *
> +dma_buf_dev_map_dma_buf(struct dma_buf_attachment *attach,
> +			enum dma_data_direction dir)
> +{
> +	struct dma_buf_dev_object *obj = attach->dmabuf->priv;
> +	struct sg_table *sgt;
> +	int ret;
> +
> +	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
> +	if (!sgt)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ret = dma_get_sgtable(obj->dev, sgt, obj->vaddr,
> +			      obj->dma_addr, obj->size);
> +	if (ret < 0)
> +		goto err_free;
> +
> +	if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) {
> +		ret = -ENOMEM;
> +		goto err_free_table;
> +	}
> +
> +	return sgt;
> +
> +err_free_table:
> +	sg_free_table(sgt);
> +err_free:
> +	kfree(sgt);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +static void dma_buf_dev_unmap_dma_buf(struct dma_buf_attachment *attach,
> +				      struct sg_table *sgt,
> +				      enum dma_data_direction dir)
> +{
> +	dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
> +	sg_free_table(sgt);
> +	kfree(sgt);
> +}
> +
> +static void dma_buf_dev_release(struct dma_buf *dma_buf)
> +{
> +	struct dma_buf_dev_object *obj = dma_buf->priv;
> +
> +/* FIXME remove */
> +pr_info("%s()\n", __func__);
> +	dma_free_attrs(obj->dev, obj->size, obj->vaddr, obj->dma_addr,
> +		       obj->attrs);
> +	kfree(obj);
> +}
> +
> +static void *dma_buf_dev_kmap(struct dma_buf *dma_buf, unsigned long page_num)
> +{
> +	struct dma_buf_dev_object *obj = dma_buf->priv;
> +
> +	return obj->vaddr + page_num * PAGE_SIZE;
> +}
> +
> +static void *dma_buf_dev_vmap(struct dma_buf *dma_buf)
> +{
> +	struct dma_buf_dev_object *obj = dma_buf->priv;
> +
> +	return obj->vaddr;
> +}
> +
> +static int dma_buf_dev_mmap(struct dma_buf *dma_buf,
> +			    struct vm_area_struct *vma)
> +{
> +	struct dma_buf_dev_object *obj = dma_buf->priv;
> +	int ret;
> +
> +	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
> +
> +	ret = dma_mmap_attrs(obj->dev, vma, obj->vaddr, obj->dma_addr,
> +			     vma->vm_end - vma->vm_start, obj->attrs);
> +
> +	return ret;
> +}
> +
> +static const struct dma_buf_ops dma_buf_dev_ops =  {
> +	.map_dma_buf = dma_buf_dev_map_dma_buf,
> +	.unmap_dma_buf = dma_buf_dev_unmap_dma_buf,
> +	.release = dma_buf_dev_release,
> +	.kmap_atomic = dma_buf_dev_kmap,
> +	.kmap = dma_buf_dev_kmap,
> +	.vmap = dma_buf_dev_vmap,
> +	.mmap = dma_buf_dev_mmap,
> +};
> +
> +struct dma_buf *dma_buf_dev_alloc_attrs(struct device *dev, size_t size,
> +					unsigned long attrs, int flags)
> +{
> +	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
> +	struct dma_buf_dev_object *obj;
> +	struct dma_buf *dmabuf;
> +	int ret;
> +
> +	if (flags & ~(O_CLOEXEC | O_ACCMODE))
> +		return ERR_PTR(-EINVAL);
> +
> +	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
> +	if (!obj)
> +		return ERR_PTR(-ENOMEM);
> +
> +	obj->dev = dev;
> +	obj->size = size;
> +	obj->attrs = attrs;
> +
> +	obj->vaddr = dma_alloc_attrs(dev, size, &obj->dma_addr, GFP_KERNEL, attrs);

Hm, does dma_alloc reall always work with dev == NULL? I had no idea this
was possible ...

Cheers, Daniel

> +	if (!obj->vaddr) {
> +		ret = -ENOMEM;
> +		goto err_free_obj;
> +	}
> +
> +	exp_info.ops = &dma_buf_dev_ops;
> +	exp_info.size = obj->size;
> +	exp_info.flags = flags;
> +	exp_info.priv = obj;
> +
> +	dmabuf = dma_buf_export(&exp_info);
> +	if (IS_ERR(dmabuf)) {
> +		ret = PTR_ERR(dmabuf);
> +		goto err_free_buf;
> +	}
> +
> +	return dmabuf;
> +
> +err_free_buf:
> +	dma_free_attrs(dev, size, obj->vaddr, obj->dma_addr, attrs);
> +err_free_obj:
> +	kfree(obj);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +static long dma_buf_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> +{
> +	struct dma_buf_dev_create create;
> +	struct dma_buf *dmabuf;
> +
> +	switch (cmd) {
> +	case DMA_BUF_DEV_IOCTL_CREATE:
> +
> +		if (copy_from_user(&create, (void __user *)arg, sizeof(create)))
> +			return -EFAULT;
> +
> +		if (!create.size)
> +			return -EINVAL;
> +
> +		dmabuf = dma_buf_dev_alloc_attrs(NULL, create.size,
> +						 create.attrs, create.flags);
> +		if (IS_ERR(dmabuf))
> +			return PTR_ERR(dmabuf);
> +
> +		create.fd = dma_buf_fd(dmabuf, create.flags);
> +		if (create.fd < 0) {
> +			dma_buf_put(dmabuf);
> +			return create.fd;
> +		}
> +
> +		if (copy_to_user((void __user *)arg, &create, sizeof(create)))
> +			return -EFAULT;
> +
> +		return 0;
> +	default:
> +		return -ENOTTY;
> +	}
> +}
> +
> +static const struct file_operations dma_buf_dev_fops = {
> +	.owner		= THIS_MODULE,
> +	.unlocked_ioctl	= dma_buf_dev_ioctl,
> +	.compat_ioctl	= dma_buf_dev_ioctl,
> +};
> +
> +static struct miscdevice dma_buf_dev_misc = {
> +	.fops		= &dma_buf_dev_fops,
> +	.minor		= MISC_DYNAMIC_MINOR,
> +	.name		= "dma-buf",
> +};
> +module_misc_device(dma_buf_dev_misc);
> +
> +MODULE_AUTHOR("Noralf Trønnes");
> +MODULE_DESCRIPTION("User mode dma-buf creation");
> +MODULE_LICENSE("GPL");
> diff --git a/include/uapi/linux/dma-buf-dev.h b/include/uapi/linux/dma-buf-dev.h
> new file mode 100644
> index 0000000..fddbe04
> --- /dev/null
> +++ b/include/uapi/linux/dma-buf-dev.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) 2016 Noralf Trønnes
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#ifndef _DMA_BUF_DEV_UAPI_H_
> +#define _DMA_BUF_DEV_UAPI_H_
> +
> +#include <linux/types.h>
> +
> +/**
> + * struct dma_buf_dev_create -
> + * @attrs: Attributes of mapping properties requested in dma_alloc_attrs
> + * @size: Buffer size
> + * @flags: Mode flags for the dma-buf file
> + * @fd: Returned dma-buf file descriptor
> + */
> +struct dma_buf_dev_create {
> +	__u64 attrs;
> +#define DMA_BUF_DEV_ATTR_WRITE_COMBINE          BIT(2)
> +	__u64 size;
> +	__u64 flags;
> +
> +	__s64 fd;
> +};
> +
> +/* FIXME: Update Documentation/ioctl/ioctl-number.txt */
> +#define DMA_BUF_DEV_BASE		0xB6
> +#define DMA_BUF_DEV_IOCTL_CREATE	_IOWR(DMA_BUF_DEV_BASE, 0, struct dma_buf_dev_create)
> +
> +#endif
> -- 
> 2.10.2
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2017-01-04 15:08 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-04 13:34 [RFC 0/6] drm: Add support for userspace drivers Noralf Trønnes
2017-01-04 13:34 ` [RFC 1/6] drm/modes: Export drm_mode_convert_umode() Noralf Trønnes
2017-01-04 13:34 ` [RFC 2/6] drm: Add support for userspace drivers Noralf Trønnes
2017-01-04 13:34 ` [RFC 3/6] dma-buf: Support generic userspace allocations Noralf Trønnes
2017-01-04 15:08   ` Daniel Vetter [this message]
2017-01-04 13:34 ` [RFC 4/6] spi: Let clients do scatter/gather transfers Noralf Trønnes
2017-01-04 13:34 ` [RFC 5/6] spi: spidev: Add dma-buf support Noralf Trønnes
2017-01-04 13:34 ` [RFC 6/6] spi: spidev: Add userspace driver support Noralf Trønnes
2017-01-04 15:06 ` [RFC 0/6] drm: Add support for userspace drivers Daniel Vetter
2017-01-04 15:15   ` Martin Peres

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20170104150855.23lu5hfzk6ciagln@phenom.ffwll.local \
    --to=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=noralf@tronnes.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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.