From patchwork Thu Dec 12 14:36:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 22317 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f198.google.com (mail-ie0-f198.google.com [209.85.223.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B698E23FBA for ; Fri, 13 Dec 2013 03:08:28 +0000 (UTC) Received: by mail-ie0-f198.google.com with SMTP id tp5sf4940952ieb.1 for ; Thu, 12 Dec 2013 19:08:28 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:cc:subject :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=ti0agHZ2G3SWb9nubn3/ICUlANQEhF045Wk+VEmBz3Q=; b=HEkalijQYcENKaeqaH2Zy6WkzHvHQpqHAnP4xKvHJsrUNiA3OR55TWLEpoON9RfZ9U B48om7wmMNj/lTNJYx2+cfnxMpDfM8uiarwcYu6jtxSHt//LLwRsk5/tlAGqVw7LkzwE AM2ueHUhx1FV2fQoNHjkZW7LqMReHIeizQ6IFz5CDEJKyHGWexigEBZS8pH0LcGbgJLL 3kwq8upbGmBHad233E5x1paeVa6NzDT77ievHN6i9tU8YT0hHnPS65UHPlMIFuD76sHD IaJ00qTCS/gEs4eNYniR5T2olr7NL1ykt/ZkvIWMPdHpoZxudjPykqACH+WLxL/QuZrL 0VUg== X-Gm-Message-State: ALoCoQkPDkKjhpdbUiodUvWgt270FSnXlnywBDAysZ6BFj0B82i86VaANSvw7gs8+81lSh5CJYzC X-Received: by 10.182.66.73 with SMTP id d9mr82850obt.8.1386904108385; Thu, 12 Dec 2013 19:08:28 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.47.9 with SMTP id z9ls793897qem.79.gmail; Thu, 12 Dec 2013 19:08:28 -0800 (PST) X-Received: by 10.224.22.200 with SMTP id o8mr434347qab.100.1386904108198; Thu, 12 Dec 2013 19:08:28 -0800 (PST) Received: from mail-vc0-x236.google.com (mail-vc0-x236.google.com [2607:f8b0:400c:c03::236]) by mx.google.com with ESMTPS id r4si251120qcl.93.2013.12.12.19.08.28 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 12 Dec 2013 19:08:28 -0800 (PST) Received-SPF: neutral (google.com: 2607:f8b0:400c:c03::236 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c03::236; Received: by mail-vc0-f182.google.com with SMTP id lc6so948877vcb.27 for ; Thu, 12 Dec 2013 19:08:28 -0800 (PST) X-Received: by 10.52.0.81 with SMTP id 17mr75835vdc.50.1386904107954; Thu, 12 Dec 2013 19:08:27 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp4566vcz; Thu, 12 Dec 2013 19:08:27 -0800 (PST) X-Received: by 10.180.99.42 with SMTP id en10mr506456wib.36.1386904103876; Thu, 12 Dec 2013 19:08:23 -0800 (PST) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id ul8si183188wjc.64.2013.12.12.19.08.23 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 12 Dec 2013 19:08:23 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1VrJ3k-0005uG-C4; Fri, 13 Dec 2013 03:05:00 +0000 Received: from mail-bk0-f51.google.com ([209.85.214.51]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Vr7LZ-0006L4-Nf for linaro-mm-sig@lists.linaro.org; Thu, 12 Dec 2013 14:34:37 +0000 Received: by mail-bk0-f51.google.com with SMTP id 6so925336bkj.10 for ; Thu, 12 Dec 2013 06:37:48 -0800 (PST) X-Received: by 10.204.232.145 with SMTP id ju17mr488101bkb.101.1386859068015; Thu, 12 Dec 2013 06:37:48 -0800 (PST) Received: from localhost (port-31954.pppoe.wtnet.de. [46.59.175.170]) by mx.google.com with ESMTPSA id bf8sm18543809bkb.14.2013.12.12.06.37.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Dec 2013 06:37:43 -0800 (PST) From: Thierry Reding To: Greg Kroah-Hartman , Sumit Semwal Date: Thu, 12 Dec 2013 15:36:29 +0100 Message-Id: <1386858989-1487-1-git-send-email-treding@nvidia.com> X-Mailer: git-send-email 1.8.4.2 X-Mailman-Approved-At: Fri, 13 Dec 2013 03:04:59 +0000 Cc: linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [Linaro-mm-sig] [RFC] dma-buf: Implement test module X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-mm-sig-bounces@lists.linaro.org Sender: linaro-mm-sig-bounces@lists.linaro.org X-Original-Sender: thierry.reding@gmail.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c03::236 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=neutral (bad format) header.i=@gmail.com; dmarc=fail (p=NONE dis=NONE) header.from=gmail.com Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 This is a simple test module that can be used to allocate, export and delete DMA-BUF objects. It can be used to test DMA-BUF sharing in systems that lack a real second driver. Signed-off-by: Thierry Reding --- drivers/base/Kconfig | 4 + drivers/base/Makefile | 1 + drivers/base/dma-buf-test.c | 308 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 drivers/base/dma-buf-test.c diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index e373671652b0..bed2abb9491b 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -200,6 +200,10 @@ config DMA_SHARED_BUFFER APIs extension; the file's descriptor can then be passed on to other driver. +config DMA_BUF_TEST + tristate "DMA-BUF test module" + depends on DMA_SHARED_BUFFER + config DMA_CMA bool "DMA Contiguous Memory Allocator" depends on HAVE_DMA_CONTIGUOUS && CMA diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 94e8a80e87f8..cad983b6626f 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG +obj-$(CONFIG_DMA_BUF_TEST) += dma-buf-test.o diff --git a/drivers/base/dma-buf-test.c b/drivers/base/dma-buf-test.c new file mode 100644 index 000000000000..f5498b74a09b --- /dev/null +++ b/drivers/base/dma-buf-test.c @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include +#include + +struct dmabuf_create { + __u32 flags; + __u32 size; +}; + +#define DMABUF_IOCTL_BASE 'D' +#define DMABUF_IOCTL_CREATE _IOWR(DMABUF_IOCTL_BASE, 0, struct dmabuf_create) +#define DMABUF_IOCTL_DELETE _IOWR(DMABUF_IOCTL_BASE, 1, int) +#define DMABUF_IOCTL_EXPORT _IOWR(DMABUF_IOCTL_BASE, 2, int) + +struct dmabuf_file { + struct dma_buf *buf; + dma_addr_t phys; + size_t size; + void *virt; +}; + +static int dmabuf_attach(struct dma_buf *buf, struct device *dev, + struct dma_buf_attachment *attach) +{ + return 0; +} + +static void dmabuf_detach(struct dma_buf *buf, + struct dma_buf_attachment *attach) +{ +} + +static struct sg_table *dmabuf_map_dma_buf(struct dma_buf_attachment *attach, + enum dma_data_direction dir) +{ + struct dmabuf_file *priv = attach->dmabuf->priv; + struct sg_table *sgt; + + sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return NULL; + + if (sg_alloc_table(sgt, 1, GFP_KERNEL)) { + kfree(sgt); + return NULL; + } + + sg_dma_address(sgt->sgl) = priv->phys; + sg_dma_len(sgt->sgl) = priv->size; + + return sgt; +} + +static void dmabuf_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction dir) +{ + sg_free_table(sgt); + kfree(sgt); +} + +static void dmabuf_release(struct dma_buf *buf) +{ +} + +static int dmabuf_begin_cpu_access(struct dma_buf *buf, size_t size, + size_t length, + enum dma_data_direction direction) +{ + return 0; +} + +static void dmabuf_end_cpu_access(struct dma_buf *buf, size_t size, + size_t length, + enum dma_data_direction direction) +{ +} + +static void *dmabuf_kmap_atomic(struct dma_buf *buf, unsigned long page) +{ + return NULL; +} + +static void dmabuf_kunmap_atomic(struct dma_buf *buf, unsigned long page, + void *vaddr) +{ +} + +static void *dmabuf_kmap(struct dma_buf *buf, unsigned long page) +{ + return NULL; +} + +static void dmabuf_kunmap(struct dma_buf *buf, unsigned long page, void *vaddr) +{ +} + +static void dmabuf_vm_open(struct vm_area_struct *vma) +{ +} + +static void dmabuf_vm_close(struct vm_area_struct *vma) +{ +} + +static int dmabuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + return 0; +} + +static const struct vm_operations_struct dmabuf_vm_ops = { + .open = dmabuf_vm_open, + .close = dmabuf_vm_close, + .fault = dmabuf_vm_fault, +}; + +static int dmabuf_mmap(struct dma_buf *buf, struct vm_area_struct *vma) +{ + pgprot_t prot = vm_get_page_prot(vma->vm_flags); + struct dmabuf_file *priv = buf->priv; + + vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; + vma->vm_ops = &dmabuf_vm_ops; + vma->vm_private_data = priv; + vma->vm_page_prot = pgprot_writecombine(prot); + + return remap_pfn_range(vma, vma->vm_start, priv->phys >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + +static void *dmabuf_vmap(struct dma_buf *buf) +{ + return NULL; +} + +static void dmabuf_vunmap(struct dma_buf *buf, void *vaddr) +{ +} + +static const struct dma_buf_ops dmabuf_ops = { + .attach = dmabuf_attach, + .detach = dmabuf_detach, + .map_dma_buf = dmabuf_map_dma_buf, + .unmap_dma_buf = dmabuf_unmap_dma_buf, + .release = dmabuf_release, + .begin_cpu_access = dmabuf_begin_cpu_access, + .end_cpu_access = dmabuf_end_cpu_access, + .kmap_atomic = dmabuf_kmap_atomic, + .kunmap_atomic = dmabuf_kunmap_atomic, + .kmap = dmabuf_kmap, + .kunmap = dmabuf_kunmap, + .mmap = dmabuf_mmap, + .vmap = dmabuf_vmap, + .vunmap = dmabuf_vunmap, +}; + +static int dmabuf_file_open(struct inode *inode, struct file *file) +{ + struct dmabuf_file *priv; + int ret = 0; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + file->private_data = priv; + + return ret; +} + +static int dmabuf_file_release(struct inode *inode, struct file *file) +{ + struct dmabuf_file *priv = file->private_data; + int ret = 0; + + if (priv->virt) + dma_free_writecombine(NULL, priv->size, priv->virt, priv->phys); + + if (priv->buf) + dma_buf_put(priv->buf); + + kfree(priv); + + return ret; +} + +static int dmabuf_ioctl_create(struct dmabuf_file *priv, const void __user *data) +{ + struct dmabuf_create args; + int ret = 0; + + if (priv->buf || priv->virt) + return -EBUSY; + + if (copy_from_user(&args, data, sizeof(args))) + return -EFAULT; + + priv->virt = dma_alloc_writecombine(NULL, args.size, &priv->phys, + GFP_KERNEL | __GFP_NOWARN); + if (!priv->virt) + return -ENOMEM; + + priv->buf = dma_buf_export(priv, &dmabuf_ops, args.size, args.flags); + if (!priv->buf) { + ret = -ENOMEM; + goto free; + } + + if (IS_ERR(priv->buf)) { + ret = PTR_ERR(priv->buf); + goto free; + } + + priv->size = args.size; + + return 0; + +free: + dma_free_writecombine(NULL, priv->size, priv->virt, priv->phys); + priv->virt = NULL; + return ret; +} + +static int dmabuf_ioctl_delete(struct dmabuf_file *priv, unsigned long flags) +{ + dma_free_writecombine(NULL, priv->size, priv->virt, priv->phys); + priv->virt = NULL; + priv->phys = 0; + priv->size = 0; + + dma_buf_put(priv->buf); + priv->buf = NULL; + + return 0; +} + +static int dmabuf_ioctl_export(struct dmabuf_file *priv, unsigned long flags) +{ + int err; + + get_dma_buf(priv->buf); + + err = dma_buf_fd(priv->buf, flags); + if (err < 0) + dma_buf_put(priv->buf); + + return err; +} + +static long dmabuf_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct dmabuf_file *priv = file->private_data; + long ret = 0; + + switch (cmd) { + case DMABUF_IOCTL_CREATE: + ret = dmabuf_ioctl_create(priv, (const void __user *)arg); + break; + + case DMABUF_IOCTL_DELETE: + ret = dmabuf_ioctl_delete(priv, arg); + break; + + case DMABUF_IOCTL_EXPORT: + ret = dmabuf_ioctl_export(priv, arg); + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +static const struct file_operations dmabuf_fops = { + .owner = THIS_MODULE, + .open = dmabuf_file_open, + .release = dmabuf_file_release, + .unlocked_ioctl = dmabuf_file_ioctl, +}; + +static struct miscdevice dmabuf_device = { + .minor = 128, + .name = "dmabuf", + .fops = &dmabuf_fops, +}; + +static int __init dmabuf_init(void) +{ + return misc_register(&dmabuf_device); +} +module_init(dmabuf_init); + +static void __exit dmabuf_exit(void) +{ + misc_deregister(&dmabuf_device); +} +module_exit(dmabuf_exit); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("DMA-BUF test driver"); +MODULE_LICENSE("GPL v2");