All of lore.kernel.org
 help / color / mirror / Atom feed
From: rmk+kernel@arm.linux.org.uk (Russell King)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH RFC 3/3] DRM: Armada: support for dma_buf import into gem
Date: Sat, 29 Jun 2013 23:55:23 +0100	[thread overview]
Message-ID: <E1Ut439-0000wv-2e@rmk-PC.arm.linux.org.uk> (raw)
In-Reply-To: <20130629225210.GF3353@n2100.arm.linux.org.uk>

Support importing certain dma_bufs back into gem - notably those which
are either contiguous or are our own exports which do not use
dma_map_sg().

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c |    4 +-
 drivers/gpu/drm/armada/armada_fb.c  |    6 +++
 drivers/gpu/drm/armada/armada_gem.c |   81 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/armada/armada_gem.h |    4 ++
 4 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e0a08e9..268ea28 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -311,9 +311,9 @@ static struct drm_driver armada_drm_driver = {
 	.gem_init_object	= NULL,
 	.gem_free_object	= armada_gem_free_object,
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
-	.prime_fd_to_handle	= NULL,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
 	.gem_prime_export	= armada_gem_prime_export,
-	.gem_prime_import	= NULL,
+	.gem_prime_import	= armada_gem_prime_import,
 	.dumb_create		= armada_gem_dumb_create,
 	.dumb_map_offset	= armada_gem_dumb_map_offset,
 	.dumb_destroy		= armada_gem_dumb_destroy,
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index 5154f04..28965e3 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -120,6 +120,12 @@ static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
 		return ERR_PTR(-ENOENT);
 	}
 
+	if (obj->obj.import_attach && !obj->sgt) {
+		ret = armada_gem_map_import(obj);
+		if (ret)
+			goto unref;
+	}
+
 	/* Framebuffer objects must have a valid device address for scanout */
 	if (obj->dev_addr == DMA_ERROR_CODE) {
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index d09fa14..ad517ce 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -70,6 +70,12 @@ void armada_gem_free_object(struct drm_gem_object *obj)
 			iounmap(dobj->addr);
 	}
 
+	if (dobj->obj.import_attach) {
+		/* We only ever display imported data */
+		dma_buf_unmap_attachment(dobj->obj.import_attach, dobj->sgt,
+					 DMA_TO_DEVICE);
+		drm_prime_gem_destroy(&dobj->obj, NULL);
+	}
 
 	drm_gem_object_release(&dobj->obj);
 
@@ -270,6 +276,12 @@ int armada_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
 		goto err_unlock;
 	}
 
+	/* Don't allow imported objects to be mapped */
+	if (obj->obj.import_attach) {
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
 	if (!obj->obj.map_list.map)
 		ret = drm_gem_create_mmap_offset(&obj->obj);
 
@@ -537,5 +549,72 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
 	int flags)
 {
 	return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
-			      flags);
+			      O_RDWR);
+}
+
+struct drm_gem_object *
+armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
+{
+	struct dma_buf_attachment *attach;
+	struct armada_gem_object *dobj;
+
+	if (buf->ops == &armada_gem_prime_dmabuf_ops) {
+		struct drm_gem_object *obj = buf->priv;
+		if (obj->dev == dev) {
+			/*
+			 * Importing our own dmabuf(s) increases the
+			 * refcount on the gem object itself.
+			 */
+			drm_gem_object_reference(obj);
+			dma_buf_put(buf);
+			return obj;
+		}
+	}
+
+	attach = dma_buf_attach(buf, dev->dev);
+	if (IS_ERR(attach))
+		return ERR_CAST(attach);
+
+	dobj = armada_gem_alloc_private_object(dev, buf->size);
+	if (!dobj) {
+		dma_buf_detach(buf, attach);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dobj->obj.import_attach = attach;
+
+	/*
+	 * Don't call dma_buf_map_attachment() here - it maps the
+	 * scatterlist immediately for DMA, and this is not always
+	 * an appropriate thing to do.
+	 */
+	return &dobj->obj;
+}
+
+int armada_gem_map_import(struct armada_gem_object *dobj)
+{
+	int ret;
+
+	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
+					  DMA_TO_DEVICE);
+	if (!dobj->sgt) {
+		DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
+		return -EINVAL;
+	}
+	if (IS_ERR(dobj->sgt)) {
+		ret = PTR_ERR(dobj->sgt);
+		dobj->sgt = NULL;
+		DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
+		return ret;
+	}
+	if (dobj->sgt->nents > 1) {
+		DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
+		return -EINVAL;
+	}
+	if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
+		DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
+		return -EINVAL;
+	}
+	dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
+	return 0;
 }
diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h
index e3bce9f..00b6cd4 100644
--- a/drivers/gpu/drm/armada/armada_gem.h
+++ b/drivers/gpu/drm/armada/armada_gem.h
@@ -16,6 +16,7 @@ struct armada_gem_object {
 	resource_size_t		dev_addr;
 	struct drm_mm_node	*linear;	/* for linear backed */
 	struct page		*page;		/* for page backed */
+	struct sg_table		*sgt;		/* for imported */
 	void			(*update)(void *);
 	void			*update_data;
 };
@@ -37,6 +38,9 @@ int armada_gem_dumb_destroy(struct drm_file *, struct drm_device *,
 	uint32_t);
 struct dma_buf *armada_gem_prime_export(struct drm_device *dev,
 	struct drm_gem_object *obj, int flags);
+struct drm_gem_object *armada_gem_prime_import(struct drm_device *,
+	struct dma_buf *);
+int armada_gem_map_import(struct armada_gem_object *);
 
 static inline struct armada_gem_object *armada_gem_object_lookup(
 	struct drm_device *dev, struct drm_file *dfile, unsigned handle)
-- 
1.7.4.4

WARNING: multiple messages have this Message-ID (diff)
From: Russell King <rmk+kernel@arm.linux.org.uk>
To: linux-arm-kernel@lists.infradead.org
Cc: David Airlie <airlied@linux.ie>,
	dri-devel@lists.freedesktop.org,
	Jason Cooper <jason@lakedaemon.net>,
	Daniel Vetter <daniel@ffwll.ch>,
	Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Subject: [PATCH RFC 3/3] DRM: Armada: support for dma_buf import into gem
Date: Sat, 29 Jun 2013 23:55:23 +0100	[thread overview]
Message-ID: <E1Ut439-0000wv-2e@rmk-PC.arm.linux.org.uk> (raw)
In-Reply-To: <20130629225210.GF3353@n2100.arm.linux.org.uk>

Support importing certain dma_bufs back into gem - notably those which
are either contiguous or are our own exports which do not use
dma_map_sg().

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c |    4 +-
 drivers/gpu/drm/armada/armada_fb.c  |    6 +++
 drivers/gpu/drm/armada/armada_gem.c |   81 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/armada/armada_gem.h |    4 ++
 4 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index e0a08e9..268ea28 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -311,9 +311,9 @@ static struct drm_driver armada_drm_driver = {
 	.gem_init_object	= NULL,
 	.gem_free_object	= armada_gem_free_object,
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
-	.prime_fd_to_handle	= NULL,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
 	.gem_prime_export	= armada_gem_prime_export,
-	.gem_prime_import	= NULL,
+	.gem_prime_import	= armada_gem_prime_import,
 	.dumb_create		= armada_gem_dumb_create,
 	.dumb_map_offset	= armada_gem_dumb_map_offset,
 	.dumb_destroy		= armada_gem_dumb_destroy,
diff --git a/drivers/gpu/drm/armada/armada_fb.c b/drivers/gpu/drm/armada/armada_fb.c
index 5154f04..28965e3 100644
--- a/drivers/gpu/drm/armada/armada_fb.c
+++ b/drivers/gpu/drm/armada/armada_fb.c
@@ -120,6 +120,12 @@ static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
 		return ERR_PTR(-ENOENT);
 	}
 
+	if (obj->obj.import_attach && !obj->sgt) {
+		ret = armada_gem_map_import(obj);
+		if (ret)
+			goto unref;
+	}
+
 	/* Framebuffer objects must have a valid device address for scanout */
 	if (obj->dev_addr == DMA_ERROR_CODE) {
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index d09fa14..ad517ce 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -70,6 +70,12 @@ void armada_gem_free_object(struct drm_gem_object *obj)
 			iounmap(dobj->addr);
 	}
 
+	if (dobj->obj.import_attach) {
+		/* We only ever display imported data */
+		dma_buf_unmap_attachment(dobj->obj.import_attach, dobj->sgt,
+					 DMA_TO_DEVICE);
+		drm_prime_gem_destroy(&dobj->obj, NULL);
+	}
 
 	drm_gem_object_release(&dobj->obj);
 
@@ -270,6 +276,12 @@ int armada_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
 		goto err_unlock;
 	}
 
+	/* Don't allow imported objects to be mapped */
+	if (obj->obj.import_attach) {
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
 	if (!obj->obj.map_list.map)
 		ret = drm_gem_create_mmap_offset(&obj->obj);
 
@@ -537,5 +549,72 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
 	int flags)
 {
 	return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
-			      flags);
+			      O_RDWR);
+}
+
+struct drm_gem_object *
+armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
+{
+	struct dma_buf_attachment *attach;
+	struct armada_gem_object *dobj;
+
+	if (buf->ops == &armada_gem_prime_dmabuf_ops) {
+		struct drm_gem_object *obj = buf->priv;
+		if (obj->dev == dev) {
+			/*
+			 * Importing our own dmabuf(s) increases the
+			 * refcount on the gem object itself.
+			 */
+			drm_gem_object_reference(obj);
+			dma_buf_put(buf);
+			return obj;
+		}
+	}
+
+	attach = dma_buf_attach(buf, dev->dev);
+	if (IS_ERR(attach))
+		return ERR_CAST(attach);
+
+	dobj = armada_gem_alloc_private_object(dev, buf->size);
+	if (!dobj) {
+		dma_buf_detach(buf, attach);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dobj->obj.import_attach = attach;
+
+	/*
+	 * Don't call dma_buf_map_attachment() here - it maps the
+	 * scatterlist immediately for DMA, and this is not always
+	 * an appropriate thing to do.
+	 */
+	return &dobj->obj;
+}
+
+int armada_gem_map_import(struct armada_gem_object *dobj)
+{
+	int ret;
+
+	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
+					  DMA_TO_DEVICE);
+	if (!dobj->sgt) {
+		DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
+		return -EINVAL;
+	}
+	if (IS_ERR(dobj->sgt)) {
+		ret = PTR_ERR(dobj->sgt);
+		dobj->sgt = NULL;
+		DRM_ERROR("dma_buf_map_attachment() error: %d\n", ret);
+		return ret;
+	}
+	if (dobj->sgt->nents > 1) {
+		DRM_ERROR("dma_buf_map_attachment() returned an (unsupported) scattered list\n");
+		return -EINVAL;
+	}
+	if (sg_dma_len(dobj->sgt->sgl) < dobj->obj.size) {
+		DRM_ERROR("dma_buf_map_attachment() returned a small buffer\n");
+		return -EINVAL;
+	}
+	dobj->dev_addr = sg_dma_address(dobj->sgt->sgl);
+	return 0;
 }
diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h
index e3bce9f..00b6cd4 100644
--- a/drivers/gpu/drm/armada/armada_gem.h
+++ b/drivers/gpu/drm/armada/armada_gem.h
@@ -16,6 +16,7 @@ struct armada_gem_object {
 	resource_size_t		dev_addr;
 	struct drm_mm_node	*linear;	/* for linear backed */
 	struct page		*page;		/* for page backed */
+	struct sg_table		*sgt;		/* for imported */
 	void			(*update)(void *);
 	void			*update_data;
 };
@@ -37,6 +38,9 @@ int armada_gem_dumb_destroy(struct drm_file *, struct drm_device *,
 	uint32_t);
 struct dma_buf *armada_gem_prime_export(struct drm_device *dev,
 	struct drm_gem_object *obj, int flags);
+struct drm_gem_object *armada_gem_prime_import(struct drm_device *,
+	struct dma_buf *);
+int armada_gem_map_import(struct armada_gem_object *);
 
 static inline struct armada_gem_object *armada_gem_object_lookup(
 	struct drm_device *dev, struct drm_file *dfile, unsigned handle)
-- 
1.7.4.4

  parent reply	other threads:[~2013-06-29 22:55 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-29 22:52 [PATCH RFC v4 0/3] Armada DRM driver Russell King - ARM Linux
2013-06-29 22:52 ` Russell King - ARM Linux
2013-06-29 22:53 ` [PATCH RFC 1/3] DRM: Armada: Add " Russell King
2013-06-29 22:56   ` Russell King
2013-06-30 11:59   ` Daniel Vetter
2013-06-30 11:59     ` Daniel Vetter
2013-06-30 12:52     ` Russell King - ARM Linux
2013-06-30 12:52       ` Russell King - ARM Linux
2013-06-30 17:29       ` Daniel Vetter
2013-06-30 17:29         ` Daniel Vetter
2013-07-02 18:01         ` Ville Syrjälä
2013-07-02 18:01           ` Ville Syrjälä
2013-07-02 18:23           ` Russell King - ARM Linux
2013-07-02 18:23             ` Russell King - ARM Linux
2013-07-02 18:52             ` Ville Syrjälä
2013-07-02 18:52               ` Ville Syrjälä
2013-07-01  0:01       ` Dave Airlie
2013-07-01  0:01         ` Dave Airlie
2013-07-01  0:17         ` Russell King - ARM Linux
2013-07-01  0:17           ` Russell King - ARM Linux
2013-07-01  0:40           ` Dave Airlie
2013-07-01  0:40             ` Dave Airlie
2013-07-01  8:52         ` Sebastian Hesselbarth
2013-07-01  8:52           ` Sebastian Hesselbarth
2013-07-01  9:42           ` Daniel Vetter
2013-07-01  9:42             ` Daniel Vetter
2013-07-01 10:50             ` Sebastian Hesselbarth
2013-07-01 10:50               ` Sebastian Hesselbarth
2013-07-01 21:26               ` Dave Airlie
2013-07-01 21:26                 ` Dave Airlie
2013-07-01 23:33                 ` Rob Clark
2013-07-01 23:33                   ` Rob Clark
2013-07-01 21:55           ` Rob Clark
2013-07-01 21:55             ` Rob Clark
2013-07-01 22:07             ` Sebastian Hesselbarth
2013-07-01 22:07               ` Sebastian Hesselbarth
2013-06-30 12:37   ` Daniel Vetter
2013-06-30 12:37     ` Daniel Vetter
2013-06-30 13:04     ` Russell King - ARM Linux
2013-06-30 13:04       ` Russell King - ARM Linux
2013-06-30 13:41       ` Russell King - ARM Linux
2013-06-30 13:41         ` Russell King - ARM Linux
2013-06-30 13:53         ` Russell King - ARM Linux
2013-06-30 13:53           ` Russell King - ARM Linux
2013-06-30 16:58         ` Daniel Vetter
2013-06-30 16:58           ` Daniel Vetter
2013-06-29 22:54 ` [PATCH RFC 2/3] DRM: Armada: Add support for ARGB 32x64 or 64x32 hardware cursors Russell King
2013-06-29 22:54   ` Russell King
2013-06-29 22:55 ` Russell King [this message]
2013-06-29 22:55   ` [PATCH RFC 3/3] DRM: Armada: support for dma_buf import into gem Russell King

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=E1Ut439-0000wv-2e@rmk-PC.arm.linux.org.uk \
    --to=rmk+kernel@arm.linux.org.uk \
    --cc=linux-arm-kernel@lists.infradead.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.