<div dir="ltr">Sorry I forgot to remove the Change-Id lines for these 2 patches. Please review and I'll send updated patches with the Change-Id lines removed.<br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 12, 2014 at 6:33 PM, Haixia Shi <span dir="ltr"><<a href="mailto:hshi@chromium.org" target="_blank">hshi@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Only importing an FD to a handle is currently supported on UDL,<br>
but the exporting functionality is equally useful.<br>
<br>
Change-Id: If4983041875ebf3bd2ecf996d0771eb77b0cf1dc<br>
Signed-off-by: Haixia Shi <<a href="mailto:hshi@chromium.org">hshi@chromium.org</a>><br>
Reviewed-by: Stéphane Marchesin <<a href="mailto:marcheu@chromium.org">marcheu@chromium.org</a>><br>
---<br>
drivers/gpu/drm/udl/Makefile | 2 +-<br>
drivers/gpu/drm/udl/udl_dmabuf.c | 273 +++++++++++++++++++++++++++++++++++++++<br>
drivers/gpu/drm/udl/udl_drv.c | 2 +<br>
drivers/gpu/drm/udl/udl_drv.h | 2 +<br>
drivers/gpu/drm/udl/udl_gem.c | 71 ----------<br>
5 files changed, 278 insertions(+), 72 deletions(-)<br>
create mode 100644 drivers/gpu/drm/udl/udl_dmabuf.c<br>
<br>
diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile<br>
index 05c7481..195bcac 100644<br>
--- a/drivers/gpu/drm/udl/Makefile<br>
+++ b/drivers/gpu/drm/udl/Makefile<br>
@@ -1,6 +1,6 @@<br>
<br>
ccflags-y := -Iinclude/drm<br>
<br>
-udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_encoder.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o<br>
+udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_encoder.o udl_main.o udl_fb.o udl_transfer.o udl_gem.o udl_dmabuf.o<br>
<br>
obj-$(CONFIG_DRM_UDL) := udl.o<br>
diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c<br>
new file mode 100644<br>
index 0000000..1d85c3a<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/udl/udl_dmabuf.c<br>
@@ -0,0 +1,273 @@<br>
+/*<br>
+ * udl_dmabuf.c<br>
+ *<br>
+ * Copyright (c) 2014 The Chromium OS Authors<br>
+ *<br>
+ * This program is free software; you can redistribute it and/or modify it<br>
+ * under the terms of the GNU General Public License as published by the<br>
+ * Free Software Foundation; either version 2 of the License, or (at your<br>
+ * option) any later version.<br>
+ *<br>
+ * This program is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
+ * GNU General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU General Public License<br>
+ * along with this program. If not, see <<a href="http://www.gnu.org/licenses/" target="_blank">http://www.gnu.org/licenses/</a>>.<br>
+ */<br>
+<br>
+#include <drm/drmP.h><br>
+#include "udl_drv.h"<br>
+#include <linux/shmem_fs.h><br>
+#include <linux/dma-buf.h><br>
+<br>
+struct udl_drm_dmabuf_attachment {<br>
+ struct sg_table sgt;<br>
+ enum dma_data_direction dir;<br>
+ bool is_mapped;<br>
+};<br>
+<br>
+static int udl_attach_dma_buf(struct dma_buf *dmabuf,<br>
+ struct device *dev,<br>
+ struct dma_buf_attachment *attach)<br>
+{<br>
+ struct udl_drm_dmabuf_attachment *udl_attach;<br>
+<br>
+ DRM_DEBUG_PRIME("[DEV:%s] size:%zd\n", dev_name(attach->dev),<br>
+ attach->dmabuf->size);<br>
+<br>
+ udl_attach = kzalloc(sizeof(*udl_attach), GFP_KERNEL);<br>
+ if (!udl_attach)<br>
+ return -ENOMEM;<br>
+<br>
+ udl_attach->dir = DMA_NONE;<br>
+ attach->priv = udl_attach;<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static void udl_detach_dma_buf(struct dma_buf *dmabuf,<br>
+ struct dma_buf_attachment *attach)<br>
+{<br>
+ struct udl_drm_dmabuf_attachment *udl_attach = attach->priv;<br>
+ struct sg_table *sgt;<br>
+<br>
+ if (!udl_attach)<br>
+ return;<br>
+<br>
+ DRM_DEBUG_PRIME("[DEV:%s] size:%zd\n", dev_name(attach->dev),<br>
+ attach->dmabuf->size);<br>
+<br>
+ sgt = &udl_attach->sgt;<br>
+<br>
+ if (udl_attach->dir != DMA_NONE)<br>
+ dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,<br>
+ udl_attach->dir);<br>
+<br>
+ sg_free_table(sgt);<br>
+ kfree(udl_attach);<br>
+ attach->priv = NULL;<br>
+}<br>
+<br>
+static struct sg_table *udl_map_dma_buf(struct dma_buf_attachment *attach,<br>
+ enum dma_data_direction dir)<br>
+{<br>
+ struct udl_drm_dmabuf_attachment *udl_attach = attach->priv;<br>
+ struct udl_gem_object *obj = to_udl_bo(attach->dmabuf->priv);<br>
+ struct drm_device *dev = obj->base.dev;<br>
+ struct scatterlist *rd, *wr;<br>
+ struct sg_table *sgt = NULL;<br>
+ unsigned int i;<br>
+ int page_count;<br>
+ int nents, ret;<br>
+<br>
+ DRM_DEBUG_PRIME("[DEV:%s] size:%zd dir=%d\n", dev_name(attach->dev),<br>
+ attach->dmabuf->size, dir);<br>
+<br>
+ /* just return current sgt if already requested. */<br>
+ if (udl_attach->dir == dir && udl_attach->is_mapped)<br>
+ return &udl_attach->sgt;<br>
+<br>
+ if (!obj->pages) {<br>
+ DRM_ERROR("pages is null.\n");<br>
+ return ERR_PTR(-ENOMEM);<br>
+ }<br>
+<br>
+ page_count = obj->base.size / PAGE_SIZE;<br>
+ obj->sg = drm_prime_pages_to_sg(obj->pages, page_count);<br>
+ if (!obj->sg) {<br>
+ DRM_ERROR("sg is null.\n");<br>
+ return ERR_PTR(-ENOMEM);<br>
+ }<br>
+<br>
+ sgt = &udl_attach->sgt;<br>
+<br>
+ ret = sg_alloc_table(sgt, obj->sg->orig_nents, GFP_KERNEL);<br>
+ if (ret) {<br>
+ DRM_ERROR("failed to alloc sgt.\n");<br>
+ return ERR_PTR(-ENOMEM);<br>
+ }<br>
+<br>
+ mutex_lock(&dev->struct_mutex);<br>
+<br>
+ rd = obj->sg->sgl;<br>
+ wr = sgt->sgl;<br>
+ for (i = 0; i < sgt->orig_nents; ++i) {<br>
+ sg_set_page(wr, sg_page(rd), rd->length, rd->offset);<br>
+ rd = sg_next(rd);<br>
+ wr = sg_next(wr);<br>
+ }<br>
+<br>
+ if (dir != DMA_NONE) {<br>
+ nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);<br>
+ if (!nents) {<br>
+ DRM_ERROR("failed to map sgl with iommu.\n");<br>
+ sg_free_table(sgt);<br>
+ sgt = ERR_PTR(-EIO);<br>
+ goto err_unlock;<br>
+ }<br>
+ }<br>
+<br>
+ udl_attach->is_mapped = true;<br>
+ udl_attach->dir = dir;<br>
+ attach->priv = udl_attach;<br>
+<br>
+err_unlock:<br>
+ mutex_unlock(&dev->struct_mutex);<br>
+ return sgt;<br>
+}<br>
+<br>
+static void udl_unmap_dma_buf(struct dma_buf_attachment *attach,<br>
+ struct sg_table *sgt,<br>
+ enum dma_data_direction dir)<br>
+{<br>
+ /* Nothing to do. */<br>
+ DRM_DEBUG_PRIME("[DEV:%s] size:%zd dir:%d\n", dev_name(attach->dev),<br>
+ attach->dmabuf->size, dir);<br>
+}<br>
+<br>
+static void *udl_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)<br>
+{<br>
+ /* TODO */<br>
+<br>
+ return NULL;<br>
+}<br>
+<br>
+static void *udl_dmabuf_kmap_atomic(struct dma_buf *dma_buf,<br>
+ unsigned long page_num)<br>
+{<br>
+ /* TODO */<br>
+<br>
+ return NULL;<br>
+}<br>
+<br>
+static void udl_dmabuf_kunmap(struct dma_buf *dma_buf,<br>
+ unsigned long page_num, void *addr)<br>
+{<br>
+ /* TODO */<br>
+}<br>
+<br>
+static void udl_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,<br>
+ unsigned long page_num,<br>
+ void *addr)<br>
+{<br>
+ /* TODO */<br>
+}<br>
+<br>
+static int udl_dmabuf_mmap(struct dma_buf *dma_buf,<br>
+ struct vm_area_struct *vma)<br>
+{<br>
+ /* TODO */<br>
+<br>
+ return -EINVAL;<br>
+}<br>
+<br>
+static struct dma_buf_ops udl_dmabuf_ops = {<br>
+ .attach = udl_attach_dma_buf,<br>
+ .detach = udl_detach_dma_buf,<br>
+ .map_dma_buf = udl_map_dma_buf,<br>
+ .unmap_dma_buf = udl_unmap_dma_buf,<br>
+ .kmap = udl_dmabuf_kmap,<br>
+ .kmap_atomic = udl_dmabuf_kmap_atomic,<br>
+ .kunmap = udl_dmabuf_kunmap,<br>
+ .kunmap_atomic = udl_dmabuf_kunmap_atomic,<br>
+ .mmap = udl_dmabuf_mmap,<br>
+ .release = drm_gem_dmabuf_release,<br>
+};<br>
+<br>
+struct dma_buf *udl_gem_prime_export(struct drm_device *dev,<br>
+ struct drm_gem_object *obj, int flags)<br>
+{<br>
+ return dma_buf_export(obj, &udl_dmabuf_ops, obj->size, flags, NULL);<br>
+}<br>
+<br>
+static int udl_prime_create(struct drm_device *dev,<br>
+ size_t size,<br>
+ struct sg_table *sg,<br>
+ struct udl_gem_object **obj_p)<br>
+{<br>
+ struct udl_gem_object *obj;<br>
+ int npages;<br>
+<br>
+ npages = size / PAGE_SIZE;<br>
+<br>
+ *obj_p = NULL;<br>
+ obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE);<br>
+ if (!obj)<br>
+ return -ENOMEM;<br>
+<br>
+ obj->sg = sg;<br>
+ obj->pages = drm_malloc_ab(npages, sizeof(struct page *));<br>
+ if (obj->pages == NULL) {<br>
+ DRM_ERROR("obj pages is NULL %d\n", npages);<br>
+ return -ENOMEM;<br>
+ }<br>
+<br>
+ drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);<br>
+<br>
+ *obj_p = obj;<br>
+ return 0;<br>
+}<br>
+<br>
+struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,<br>
+ struct dma_buf *dma_buf)<br>
+{<br>
+ struct dma_buf_attachment *attach;<br>
+ struct sg_table *sg;<br>
+ struct udl_gem_object *uobj;<br>
+ int ret;<br>
+<br>
+ /* need to attach */<br>
+ get_device(dev->dev);<br>
+ attach = dma_buf_attach(dma_buf, dev->dev);<br>
+ if (IS_ERR(attach)) {<br>
+ put_device(dev->dev);<br>
+ return ERR_CAST(attach);<br>
+ }<br>
+<br>
+ get_dma_buf(dma_buf);<br>
+<br>
+ sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);<br>
+ if (IS_ERR(sg)) {<br>
+ ret = PTR_ERR(sg);<br>
+ goto fail_detach;<br>
+ }<br>
+<br>
+ ret = udl_prime_create(dev, dma_buf->size, sg, &uobj);<br>
+ if (ret)<br>
+ goto fail_unmap;<br>
+<br>
+ uobj->base.import_attach = attach;<br>
+ uobj->flags = UDL_BO_WC;<br>
+<br>
+ return &uobj->base;<br>
+<br>
+fail_unmap:<br>
+ dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);<br>
+fail_detach:<br>
+ dma_buf_detach(dma_buf, attach);<br>
+ dma_buf_put(dma_buf);<br>
+ put_device(dev->dev);<br>
+ return ERR_PTR(ret);<br>
+}<br>
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c<br>
index 8607e9e..d5728ec 100644<br>
--- a/drivers/gpu/drm/udl/udl_drv.c<br>
+++ b/drivers/gpu/drm/udl/udl_drv.c<br>
@@ -51,7 +51,9 @@ static struct drm_driver driver = {<br>
.dumb_destroy = drm_gem_dumb_destroy,<br>
.fops = &udl_driver_fops,<br>
<br>
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,<br>
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,<br>
+ .gem_prime_export = udl_gem_prime_export,<br>
.gem_prime_import = udl_gem_prime_import,<br>
<br>
.name = DRIVER_NAME,<br>
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h<br>
index 3082780..1b132d7 100644<br>
--- a/drivers/gpu/drm/udl/udl_drv.h<br>
+++ b/drivers/gpu/drm/udl/udl_drv.h<br>
@@ -124,6 +124,8 @@ int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev,<br>
void udl_gem_free_object(struct drm_gem_object *gem_obj);<br>
struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,<br>
size_t size);<br>
+struct dma_buf *udl_gem_prime_export(struct drm_device *dev,<br>
+ struct drm_gem_object *obj, int flags);<br>
struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,<br>
struct dma_buf *dma_buf);<br>
<br>
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c<br>
index e00459d..692d6f2 100644<br>
--- a/drivers/gpu/drm/udl/udl_gem.c<br>
+++ b/drivers/gpu/drm/udl/udl_gem.c<br>
@@ -240,74 +240,3 @@ unlock:<br>
mutex_unlock(&dev->struct_mutex);<br>
return ret;<br>
}<br>
-<br>
-static int udl_prime_create(struct drm_device *dev,<br>
- size_t size,<br>
- struct sg_table *sg,<br>
- struct udl_gem_object **obj_p)<br>
-{<br>
- struct udl_gem_object *obj;<br>
- int npages;<br>
-<br>
- npages = size / PAGE_SIZE;<br>
-<br>
- *obj_p = NULL;<br>
- obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE);<br>
- if (!obj)<br>
- return -ENOMEM;<br>
-<br>
- obj->sg = sg;<br>
- obj->pages = drm_malloc_ab(npages, sizeof(struct page *));<br>
- if (obj->pages == NULL) {<br>
- DRM_ERROR("obj pages is NULL %d\n", npages);<br>
- return -ENOMEM;<br>
- }<br>
-<br>
- drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);<br>
-<br>
- *obj_p = obj;<br>
- return 0;<br>
-}<br>
-<br>
-struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,<br>
- struct dma_buf *dma_buf)<br>
-{<br>
- struct dma_buf_attachment *attach;<br>
- struct sg_table *sg;<br>
- struct udl_gem_object *uobj;<br>
- int ret;<br>
-<br>
- /* need to attach */<br>
- get_device(dev->dev);<br>
- attach = dma_buf_attach(dma_buf, dev->dev);<br>
- if (IS_ERR(attach)) {<br>
- put_device(dev->dev);<br>
- return ERR_CAST(attach);<br>
- }<br>
-<br>
- get_dma_buf(dma_buf);<br>
-<br>
- sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);<br>
- if (IS_ERR(sg)) {<br>
- ret = PTR_ERR(sg);<br>
- goto fail_detach;<br>
- }<br>
-<br>
- ret = udl_prime_create(dev, dma_buf->size, sg, &uobj);<br>
- if (ret) {<br>
- goto fail_unmap;<br>
- }<br>
-<br>
- uobj->base.import_attach = attach;<br>
- uobj->flags = UDL_BO_WC;<br>
-<br>
- return &uobj->base;<br>
-<br>
-fail_unmap:<br>
- dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);<br>
-fail_detach:<br>
- dma_buf_detach(dma_buf, attach);<br>
- dma_buf_put(dma_buf);<br>
- put_device(dev->dev);<br>
- return ERR_PTR(ret);<br>
-}<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.1.0.rc2.206.gedb03e5<br>
<br>
</font></span></blockquote></div><br></div></div>