* [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach
@ 2018-04-11 13:39 Christian König
2018-04-11 13:39 ` [PATCH 2/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Christian König @ 2018-04-11 13:39 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx
Move the parameters into a structure to make it simpler to extend it in
follow up patches.
This also adds the importer private as parameter so that we can directly
work with a completely filled in attachment structure.
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/dma-buf/dma-buf.c | 15 ++++++++-------
drivers/gpu/drm/armada/armada_gem.c | 6 +++++-
drivers/gpu/drm/drm_prime.c | 6 +++++-
drivers/gpu/drm/i915/i915_gem_dmabuf.c | 6 +++++-
drivers/gpu/drm/tegra/gem.c | 6 +++++-
drivers/gpu/drm/udl/udl_dmabuf.c | 6 +++++-
drivers/media/common/videobuf2/videobuf2-dma-contig.c | 6 +++++-
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 6 +++++-
drivers/staging/media/tegra-vde/tegra-vde.c | 6 +++++-
include/linux/dma-buf.h | 17 +++++++++++++++--
10 files changed, 63 insertions(+), 17 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index d78d5fc173dc..4b46982c6d9c 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -534,8 +534,9 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
/**
* dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
* calls attach() of dma_buf_ops to allow device-specific attach functionality
- * @dmabuf: [in] buffer to attach device to.
- * @dev: [in] device to be attached.
+ * @info: [in] holds all the attach related information provided
+ * by the importer. see &struct dma_buf_attach_info
+ * for further details.
*
* Returns struct dma_buf_attachment pointer for this attachment. Attachments
* must be cleaned up by calling dma_buf_detach().
@@ -549,26 +550,26 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
* accessible to @dev, and cannot be moved to a more suitable place. This is
* indicated with the error code -EBUSY.
*/
-struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev)
+struct dma_buf_attachment *dma_buf_attach(const struct dma_buf_attach_info *info)
{
+ struct dma_buf *dmabuf = info->dmabuf;
struct dma_buf_attachment *attach;
int ret;
- if (WARN_ON(!dmabuf || !dev))
+ if (WARN_ON(!dmabuf || !info->dev))
return ERR_PTR(-EINVAL);
attach = kzalloc(sizeof(*attach), GFP_KERNEL);
if (!attach)
return ERR_PTR(-ENOMEM);
- attach->dev = dev;
+ attach->dev = info->dev;
attach->dmabuf = dmabuf;
mutex_lock(&dmabuf->lock);
if (dmabuf->ops->attach) {
- ret = dmabuf->ops->attach(dmabuf, dev, attach);
+ ret = dmabuf->ops->attach(dmabuf, info->dev, attach);
if (ret)
goto err_attach;
}
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index a97f509743a5..f4d1c11f57ea 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -514,6 +514,10 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
struct drm_gem_object *
armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev->dev,
+ .dmabuf = buf
+ };
struct dma_buf_attachment *attach;
struct armada_gem_object *dobj;
@@ -529,7 +533,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf)
}
}
- attach = dma_buf_attach(buf, dev->dev);
+ attach = dma_buf_attach(&attach_info);
if (IS_ERR(attach))
return ERR_CAST(attach);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 7856a9b3f8a8..4da242de51c2 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -707,6 +707,10 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
struct dma_buf *dma_buf,
struct device *attach_dev)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = attach_dev,
+ .dmabuf = dma_buf
+ };
struct dma_buf_attachment *attach;
struct sg_table *sgt;
struct drm_gem_object *obj;
@@ -727,7 +731,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
if (!dev->driver->gem_prime_import_sg_table)
return ERR_PTR(-EINVAL);
- attach = dma_buf_attach(dma_buf, attach_dev);
+ attach = dma_buf_attach(&attach_info);
if (IS_ERR(attach))
return ERR_CAST(attach);
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 69a7aec49e84..7b737a883106 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -288,6 +288,10 @@ static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev->dev,
+ .dmabuf = dma_buf
+ };
struct dma_buf_attachment *attach;
struct drm_i915_gem_object *obj;
int ret;
@@ -306,7 +310,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
}
/* need to attach */
- attach = dma_buf_attach(dma_buf, dev->dev);
+ attach = dma_buf_attach(&attach_info);
if (IS_ERR(attach))
return ERR_CAST(attach);
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 8b0b4ff64bb4..1f2bee91e0ad 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -332,6 +332,10 @@ struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,
static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
struct dma_buf *buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = drm->dev,
+ .dmabuf = buf
+ };
struct tegra_drm *tegra = drm->dev_private;
struct dma_buf_attachment *attach;
struct tegra_bo *bo;
@@ -341,7 +345,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
if (IS_ERR(bo))
return bo;
- attach = dma_buf_attach(buf, drm->dev);
+ attach = dma_buf_attach(&attach_info);
if (IS_ERR(attach)) {
err = PTR_ERR(attach);
goto free;
diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c
index 2867ed155ff6..c4db84abe231 100644
--- a/drivers/gpu/drm/udl/udl_dmabuf.c
+++ b/drivers/gpu/drm/udl/udl_dmabuf.c
@@ -243,6 +243,10 @@ static int udl_prime_create(struct drm_device *dev,
struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev->dev,
+ .dmabuf = dma_buf
+ };
struct dma_buf_attachment *attach;
struct sg_table *sg;
struct udl_gem_object *uobj;
@@ -250,7 +254,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
/* need to attach */
get_device(dev->dev);
- attach = dma_buf_attach(dma_buf, dev->dev);
+ attach = dma_buf_attach(&attach_info);
if (IS_ERR(attach)) {
put_device(dev->dev);
return ERR_CAST(attach);
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index f1178f6f434d..93bd1f40f756 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -677,6 +677,10 @@ static void vb2_dc_detach_dmabuf(void *mem_priv)
static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
unsigned long size, enum dma_data_direction dma_dir)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev,
+ .dmabuf = dbuf
+ };
struct vb2_dc_buf *buf;
struct dma_buf_attachment *dba;
@@ -692,7 +696,7 @@ static void *vb2_dc_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
buf->dev = dev;
/* create attachment for the dmabuf with the user device */
- dba = dma_buf_attach(dbuf, buf->dev);
+ dba = dma_buf_attach(&attach_info);
if (IS_ERR(dba)) {
pr_err("failed to attach dmabuf\n");
kfree(buf);
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 753ed3138dcc..4e61050ba87f 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -609,6 +609,10 @@ static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
unsigned long size, enum dma_data_direction dma_dir)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev,
+ .dmabuf = dbuf
+ };
struct vb2_dma_sg_buf *buf;
struct dma_buf_attachment *dba;
@@ -624,7 +628,7 @@ static void *vb2_dma_sg_attach_dmabuf(struct device *dev, struct dma_buf *dbuf,
buf->dev = dev;
/* create attachment for the dmabuf with the user device */
- dba = dma_buf_attach(dbuf, buf->dev);
+ dba = dma_buf_attach(&attach_info);
if (IS_ERR(dba)) {
pr_err("failed to attach dmabuf\n");
kfree(buf);
diff --git a/drivers/staging/media/tegra-vde/tegra-vde.c b/drivers/staging/media/tegra-vde/tegra-vde.c
index c47659e96089..25d112443b0d 100644
--- a/drivers/staging/media/tegra-vde/tegra-vde.c
+++ b/drivers/staging/media/tegra-vde/tegra-vde.c
@@ -529,6 +529,10 @@ static int tegra_vde_attach_dmabuf(struct device *dev,
size_t *size,
enum dma_data_direction dma_dir)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev,
+ .dmabuf = dmabuf
+ };
struct dma_buf_attachment *attachment;
struct dma_buf *dmabuf;
struct sg_table *sgt;
@@ -547,7 +551,7 @@ static int tegra_vde_attach_dmabuf(struct device *dev,
return -EINVAL;
}
- attachment = dma_buf_attach(dmabuf, dev);
+ attachment = dma_buf_attach(&attach_info);
if (IS_ERR(attachment)) {
dev_err(dev, "Failed to attach dmabuf\n");
err = PTR_ERR(attachment);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 085db2fee2d7..414b4dde5eb7 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -362,6 +362,19 @@ struct dma_buf_export_info {
struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \
.owner = THIS_MODULE }
+/**
+ * struct dma_buf_attach_info - holds information needed to attach to a dma_buf
+ * @dmabuf: the exported dma_buf
+ * @dev: the device which wants to import the attachment
+ *
+ * This structure holds the information required to attach to a buffer. Used
+ * with dma_buf_attach() only.
+ */
+struct dma_buf_attach_info {
+ struct dma_buf *dmabuf;
+ struct device *dev;
+};
+
/**
* get_dma_buf - convenience wrapper for get_file.
* @dmabuf: [in] pointer to dma_buf
@@ -376,8 +389,8 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
get_file(dmabuf->file);
}
-struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
- struct device *dev);
+struct dma_buf_attachment *
+dma_buf_attach(const struct dma_buf_attach_info *info);
void dma_buf_detach(struct dma_buf *dmabuf,
struct dma_buf_attachment *dmabuf_attach);
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] dma-buf: add optional invalidate_mappings callback v3
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
@ 2018-04-11 13:39 ` Christian König
2018-04-11 13:39 ` [PATCH 3/5] drm/ttm: remove the backing store if no placement is given Christian König
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Christian König @ 2018-04-11 13:39 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx
Each importer can now provide an invalidate_mappings callback.
This allows the exporter to provide the mappings without the need to pin
the backing store.
v2: don't try to invalidate mappings when the callback is NULL,
lock the reservation obj while using the attachments,
add helper to set the callback
v3: move flag for invalidation support into the DMA-buf,
use new attach_info structure to set the callback
v4: use importer_priv field instead of mangling exporter priv.
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/dma-buf/dma-buf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/dma-buf.h | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 4b46982c6d9c..ffdaab10e2f2 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -565,6 +565,8 @@ struct dma_buf_attachment *dma_buf_attach(const struct dma_buf_attach_info *info
attach->dev = info->dev;
attach->dmabuf = dmabuf;
+ attach->importer_priv = info->importer_priv;
+ attach->invalidate = info->invalidate;
mutex_lock(&dmabuf->lock);
@@ -573,7 +575,9 @@ struct dma_buf_attachment *dma_buf_attach(const struct dma_buf_attach_info *info
if (ret)
goto err_attach;
}
+ reservation_object_lock(dmabuf->resv, NULL);
list_add(&attach->node, &dmabuf->attachments);
+ reservation_object_unlock(dmabuf->resv);
mutex_unlock(&dmabuf->lock);
return attach;
@@ -599,7 +603,9 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
return;
mutex_lock(&dmabuf->lock);
+ reservation_object_lock(dmabuf->resv, NULL);
list_del(&attach->node);
+ reservation_object_unlock(dmabuf->resv);
if (dmabuf->ops->detach)
dmabuf->ops->detach(dmabuf, attach);
@@ -633,10 +639,23 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);
+ /*
+ * Mapping a DMA-buf can trigger its invalidation, prevent sending this
+ * event to the caller by temporary removing this attachment from the
+ * list.
+ */
+ if (attach->invalidate) {
+ reservation_object_assert_held(attach->dmabuf->resv);
+ list_del(&attach->node);
+ }
+
sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
if (!sg_table)
sg_table = ERR_PTR(-ENOMEM);
+ if (attach->invalidate)
+ list_add(&attach->node, &attach->dmabuf->attachments);
+
return sg_table;
}
EXPORT_SYMBOL_GPL(dma_buf_map_attachment);
@@ -657,6 +676,9 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
{
might_sleep();
+ if (attach->invalidate)
+ reservation_object_assert_held(attach->dmabuf->resv);
+
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
@@ -665,6 +687,26 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
}
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
+/**
+ * dma_buf_invalidate_mappings - invalidate all mappings of this dma_buf
+ *
+ * @dmabuf: [in] buffer which mappings should be invalidated
+ *
+ * Informs all attachmenst that they need to destroy and recreated all their
+ * mappings.
+ */
+void dma_buf_invalidate_mappings(struct dma_buf *dmabuf)
+{
+ struct dma_buf_attachment *attach;
+
+ reservation_object_assert_held(dmabuf->resv);
+
+ list_for_each_entry(attach, &dmabuf->attachments, node)
+ if (attach->invalidate)
+ attach->invalidate(attach);
+}
+EXPORT_SYMBOL_GPL(dma_buf_invalidate_mappings);
+
/**
* DOC: cpu access
*
@@ -1122,10 +1164,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
seq_puts(s, "\tAttached Devices:\n");
attach_count = 0;
+ reservation_object_lock(buf_obj->resv, NULL);
list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
attach_count++;
}
+ reservation_object_unlock(buf_obj->resv);
seq_printf(s, "Total %d devices attached\n\n",
attach_count);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 414b4dde5eb7..566503dd2b4f 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -270,6 +270,8 @@ struct dma_buf_ops {
* @poll: for userspace poll support
* @cb_excl: for userspace poll support
* @cb_shared: for userspace poll support
+ * @invalidation_supported: True when the exporter supports unpinned operation
+ * using the reservation lock.
*
* This represents a shared buffer, created by calling dma_buf_export(). The
* userspace representation is a normal file descriptor, which can be created by
@@ -293,6 +295,7 @@ struct dma_buf {
struct list_head list_node;
void *priv;
struct reservation_object *resv;
+ bool invalidation_supported;
/* poll support */
wait_queue_head_t poll;
@@ -311,6 +314,7 @@ struct dma_buf {
* @dev: device attached to the buffer.
* @node: list of dma_buf_attachment.
* @priv: exporter specific attachment data.
+ * @importer_priv: importer specific attachment data.
*
* This structure holds the attachment information between the dma_buf buffer
* and its user device(s). The list contains one attachment struct per device
@@ -326,6 +330,29 @@ struct dma_buf_attachment {
struct device *dev;
struct list_head node;
void *priv;
+ void *importer_priv;
+
+ /**
+ * @invalidate:
+ *
+ * Optional callback provided by the importer of the dma-buf.
+ *
+ * If provided the exporter can avoid pinning the backing store while
+ * mappings exists.
+ *
+ * The function is called with the lock of the reservation object
+ * associated with the dma_buf held and the mapping function must be
+ * called with this lock held as well. This makes sure that no mapping
+ * is created concurrently with an ongoing invalidation.
+ *
+ * After the callback all existing mappings are still valid until all
+ * fences in the dma_bufs reservation object are signaled, but should be
+ * destroyed by the importer as soon as possible.
+ *
+ * New mappings can be created immediately, but can't be used before the
+ * exclusive fence in the dma_bufs reservation object is signaled.
+ */
+ void (*invalidate)(struct dma_buf_attachment *attach);
};
/**
@@ -364,8 +391,10 @@ struct dma_buf_export_info {
/**
* struct dma_buf_attach_info - holds information needed to attach to a dma_buf
- * @dmabuf: the exported dma_buf
- * @dev: the device which wants to import the attachment
+ * @dmabuf: the exported dma_buf
+ * @dev: the device which wants to import the attachment
+ * @importer_priv: private data of importer to this attachment
+ * @invalidate: callback to use for invalidating mappings
*
* This structure holds the information required to attach to a buffer. Used
* with dma_buf_attach() only.
@@ -373,6 +402,8 @@ struct dma_buf_export_info {
struct dma_buf_attach_info {
struct dma_buf *dmabuf;
struct device *dev;
+ void *importer_priv;
+ void (*invalidate)(struct dma_buf_attachment *attach);
};
/**
@@ -404,6 +435,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *,
enum dma_data_direction);
void dma_buf_unmap_attachment(struct dma_buf_attachment *, struct sg_table *,
enum dma_data_direction);
+void dma_buf_invalidate_mappings(struct dma_buf *dma_buf);
int dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
enum dma_data_direction dir);
int dma_buf_end_cpu_access(struct dma_buf *dma_buf,
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] drm/ttm: remove the backing store if no placement is given
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
2018-04-11 13:39 ` [PATCH 2/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
@ 2018-04-11 13:39 ` Christian König
2018-04-11 13:39 ` [PATCH 4/5] drm/amdgpu: add independent DMA-buf export v2 Christian König
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Christian König @ 2018-04-11 13:39 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx
Pipeline removal of the BOs backing store when the placement is given
during validation.
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/ttm/ttm_bo.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 98e06f8bf23b..17e821f01d0a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1078,6 +1078,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
uint32_t new_flags;
reservation_object_assert_held(bo->resv);
+
+ /*
+ * Remove the backing store if no placement is given.
+ */
+ if (!placement->num_placement && !placement->num_busy_placement) {
+ ret = ttm_bo_pipeline_gutting(bo);
+ if (ret)
+ return ret;
+
+ return ttm_tt_create(bo, false);
+ }
+
/*
* Check whether we need to move buffer.
*/
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] drm/amdgpu: add independent DMA-buf export v2
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
2018-04-11 13:39 ` [PATCH 2/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
2018-04-11 13:39 ` [PATCH 3/5] drm/ttm: remove the backing store if no placement is given Christian König
@ 2018-04-11 13:39 ` Christian König
2018-04-11 13:39 ` [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3 Christian König
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Christian König @ 2018-04-11 13:39 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx
Instead of relying on the DRM functions just implement our own export
functions. This adds support for taking care of unpinned DMA-buf.
v2: fix unintended recursion, remove debugging leftovers
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 -
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 -
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 5 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 108 ++++++++++++++++++-----------
4 files changed, 72 insertions(+), 43 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 2babfad1fd7f..3e1727251edc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -371,7 +371,6 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
void amdgpu_gem_object_close(struct drm_gem_object *obj,
struct drm_file *file_priv);
unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
-struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *
amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 0b19482b36b8..6107b845d8a8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -890,7 +890,6 @@ static struct drm_driver kms_driver = {
.gem_prime_export = amdgpu_gem_prime_export,
.gem_prime_import = amdgpu_gem_prime_import,
.gem_prime_res_obj = amdgpu_gem_prime_res_obj,
- .gem_prime_get_sg_table = amdgpu_gem_prime_get_sg_table,
.gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table,
.gem_prime_vmap = amdgpu_gem_prime_vmap,
.gem_prime_vunmap = amdgpu_gem_prime_vunmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 9e23d6f6f3f3..15bb48cebbc4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -31,6 +31,7 @@
*/
#include <linux/list.h>
#include <linux/slab.h>
+#include <linux/dma-buf.h>
#include <drm/drmP.h>
#include <drm/amdgpu_drm.h>
#include <drm/drm_cache.h>
@@ -953,6 +954,10 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
amdgpu_bo_kunmap(abo);
+ if (abo->gem_base.dma_buf && !abo->gem_base.import_attach &&
+ bo->mem.mem_type != TTM_PL_SYSTEM)
+ dma_buf_invalidate_mappings(abo->gem_base.dma_buf);
+
/* remember the eviction */
if (evict)
atomic64_inc(&adev->num_evictions);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 4b584cb75bf4..7fef95f0fed1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -32,14 +32,6 @@
static const struct dma_buf_ops amdgpu_dmabuf_ops;
-struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
- struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
- int npages = bo->tbo.num_pages;
-
- return drm_prime_pages_to_sg(bo->tbo.ttm->pages, npages);
-}
-
void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj)
{
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
@@ -126,23 +118,22 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret);
}
-static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
- struct device *target_dev,
- struct dma_buf_attachment *attach)
+static struct sg_table *
+amdgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
+ enum dma_data_direction dir)
{
+ struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct sg_table *sgt;
long r;
- r = drm_gem_map_attach(dma_buf, target_dev, attach);
- if (r)
- return r;
-
- r = amdgpu_bo_reserve(bo, false);
- if (unlikely(r != 0))
- goto error_detach;
-
+ if (!attach->invalidate) {
+ r = amdgpu_bo_reserve(bo, false);
+ if (unlikely(r != 0))
+ return ERR_PTR(r);
+ }
if (attach->dev->driver != adev->dev->driver) {
/*
@@ -158,42 +149,77 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
}
}
- /* pin buffer into GTT */
- r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
- if (r)
+ if (!attach->invalidate) {
+ /* pin buffer into GTT */
+ r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL);
+ if (r)
+ goto error_unreserve;
+
+ } else {
+ /* move buffer into GTT */
+ struct ttm_operation_ctx ctx = { false, false };
+
+ amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT);
+ r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ if (r)
+ goto error_unreserve;
+ }
+
+ sgt = drm_prime_pages_to_sg(bo->tbo.ttm->pages, bo->tbo.num_pages);
+ if (IS_ERR(sgt)) {
+ r = PTR_ERR(sgt);
goto error_unreserve;
+ }
+
+ if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+ DMA_ATTR_SKIP_CPU_SYNC))
+ goto error_free;
if (attach->dev->driver != adev->dev->driver)
bo->prime_shared_count++;
+ if (!attach->invalidate)
+ amdgpu_bo_unreserve(bo);
+
+ return sgt;
+
+error_free:
+ sg_free_table(sgt);
+ kfree(sgt);
+ r = -ENOMEM;
+
error_unreserve:
- amdgpu_bo_unreserve(bo);
+ if (!attach->invalidate)
+ amdgpu_bo_unreserve(bo);
-error_detach:
- if (r)
- drm_gem_map_detach(dma_buf, attach);
- return r;
+ return ERR_PTR(r);
}
-static void amdgpu_gem_map_detach(struct dma_buf *dma_buf,
- struct dma_buf_attachment *attach)
+static void amdgpu_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
+ struct sg_table *sgt,
+ enum dma_data_direction dir)
{
+ struct dma_buf *dma_buf = attach->dmabuf;
struct drm_gem_object *obj = dma_buf->priv;
struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
- int ret = 0;
- ret = amdgpu_bo_reserve(bo, true);
- if (unlikely(ret != 0))
- goto error;
+ if (!attach->invalidate) {
+ amdgpu_bo_reserve(bo, true);
+ amdgpu_bo_unpin(bo);
+ }
- amdgpu_bo_unpin(bo);
if (attach->dev->driver != adev->dev->driver && bo->prime_shared_count)
bo->prime_shared_count--;
- amdgpu_bo_unreserve(bo);
-error:
- drm_gem_map_detach(dma_buf, attach);
+ if (!attach->invalidate)
+ amdgpu_bo_unreserve(bo);
+
+ if (sgt) {
+ dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+ sg_free_table(sgt);
+ kfree(sgt);
+ }
}
struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj)
@@ -232,10 +258,8 @@ static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf,
}
static const struct dma_buf_ops amdgpu_dmabuf_ops = {
- .attach = amdgpu_gem_map_attach,
- .detach = amdgpu_gem_map_detach,
- .map_dma_buf = drm_gem_map_dma_buf,
- .unmap_dma_buf = drm_gem_unmap_dma_buf,
+ .map_dma_buf = amdgpu_gem_map_dma_buf,
+ .unmap_dma_buf = amdgpu_gem_unmap_dma_buf,
.release = drm_gem_dmabuf_release,
.begin_cpu_access = amdgpu_gem_begin_cpu_access,
.map = drm_gem_dmabuf_kmap,
@@ -260,6 +284,8 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
buf = drm_gem_prime_export(dev, gobj, flags);
if (!IS_ERR(buf)) {
+ buf->invalidation_supported =
+ !!(bo->preferred_domains & AMDGPU_GEM_DOMAIN_GTT);
buf->file->f_mapping = dev->anon_inode->i_mapping;
buf->ops = &amdgpu_dmabuf_ops;
}
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
` (2 preceding siblings ...)
2018-04-11 13:39 ` [PATCH 4/5] drm/amdgpu: add independent DMA-buf export v2 Christian König
@ 2018-04-11 13:39 ` Christian König
2018-04-25 23:33 ` [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach kbuild test robot
2018-04-26 6:44 ` kbuild test robot
5 siblings, 0 replies; 8+ messages in thread
From: Christian König @ 2018-04-11 13:39 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx
Instead of relying on the DRM functions just implement our own import
functions. This adds support for taking care of unpinned DMA-buf.
v2: enable for all exporters, not just amdgpu, fix invalidation
handling, lock reservation object while setting callback
v3: change to new dma_buf attach interface
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 72 ++++++++++++++++++++++++++-----
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 32 +++++++++++---
2 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 7fef95f0fed1..58dcfba0225a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -86,28 +86,24 @@ int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma
return ret;
}
-struct drm_gem_object *
-amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
- struct dma_buf_attachment *attach,
- struct sg_table *sg)
+static struct drm_gem_object *
+amdgpu_gem_prime_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
{
- struct reservation_object *resv = attach->dmabuf->resv;
+ struct reservation_object *resv = dma_buf->resv;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_bo *bo;
int ret;
ww_mutex_lock(&resv->lock, NULL);
- ret = amdgpu_bo_create(adev, attach->dmabuf->size, PAGE_SIZE,
+ ret = amdgpu_bo_create(adev, dma_buf->size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_CPU, 0, ttm_bo_type_sg,
resv, &bo);
if (ret)
goto error;
- bo->tbo.sg = sg;
- bo->tbo.ttm->sg = sg;
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
- if (attach->dmabuf->ops != &amdgpu_dmabuf_ops)
+ if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1;
ww_mutex_unlock(&resv->lock);
@@ -118,6 +114,26 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret);
}
+struct drm_gem_object *
+amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sg)
+{
+ struct drm_gem_object *obj;
+ struct amdgpu_bo *bo;
+
+ obj = amdgpu_gem_prime_create_obj(dev, attach->dmabuf);
+ if (IS_ERR(obj))
+ return obj;
+
+ bo = gem_to_amdgpu_bo(obj);
+ amdgpu_bo_reserve(bo, true);
+ bo->tbo.sg = sg;
+ bo->tbo.ttm->sg = sg;
+ amdgpu_bo_unreserve(bo);
+ return obj;
+}
+
static struct sg_table *
amdgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
@@ -293,9 +309,29 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
return buf;
}
+static void
+amdgpu_gem_prime_invalidate_mappings(struct dma_buf_attachment *attach)
+{
+ struct ttm_operation_ctx ctx = { false, false };
+ struct drm_gem_object *obj = attach->priv;
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+ struct ttm_placement placement = {};
+ int r;
+
+ r = ttm_bo_validate(&bo->tbo, &placement, &ctx);
+ if (r)
+ DRM_ERROR("Failed to unmap DMA-buf import (%d))\n", r);
+}
+
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev->dev,
+ .dmabuf = dma_buf,
+ .invalidate = amdgpu_gem_prime_invalidate_mappings
+ };
+ struct dma_buf_attachment *attach;
struct drm_gem_object *obj;
if (dma_buf->ops == &amdgpu_dmabuf_ops) {
@@ -310,5 +346,21 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
}
}
- return drm_gem_prime_import(dev, dma_buf);
+ if (!dma_buf->invalidation_supported)
+ return drm_gem_prime_import(dev, dma_buf);
+
+ obj = amdgpu_gem_prime_create_obj(dev, dma_buf);
+ if (IS_ERR(obj))
+ return obj;
+
+ attach_info.importer_priv = obj;
+ attach = dma_buf_attach(&attach_info);
+ if (IS_ERR(attach)) {
+ drm_gem_object_put(obj);
+ return ERR_CAST(attach);
+ }
+
+ get_dma_buf(dma_buf);
+ obj->import_attach = attach;
+ return obj;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index ab73300e6c7f..2a8f328918cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -43,6 +43,7 @@
#include <linux/pagemap.h>
#include <linux/debugfs.h>
#include <linux/iommu.h>
+#include <linux/dma-buf.h>
#include "amdgpu.h"
#include "amdgpu_object.h"
#include "amdgpu_trace.h"
@@ -680,6 +681,7 @@ struct amdgpu_ttm_gup_task_list {
struct amdgpu_ttm_tt {
struct ttm_dma_tt ttm;
+ struct amdgpu_bo *bo;
u64 offset;
uint64_t userptr;
struct mm_struct *usermm;
@@ -988,6 +990,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
return NULL;
}
gtt->ttm.ttm.func = &amdgpu_backend_func;
+ gtt->bo = ttm_to_amdgpu_bo(bo);
if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) {
kfree(gtt);
return NULL;
@@ -1000,7 +1003,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
{
struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
- bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
if (gtt && gtt->userptr) {
ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
@@ -1012,7 +1014,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
return 0;
}
- if (slave && ttm->sg) {
+ if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
+ if (!ttm->sg) {
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+
+ attach = gtt->bo->gem_base.import_attach;
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sgt))
+ return PTR_ERR(sgt);
+
+ ttm->sg = sgt;
+ }
+
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
gtt->ttm.dma_address,
ttm->num_pages);
@@ -1031,9 +1045,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
{
- struct amdgpu_device *adev;
struct amdgpu_ttm_tt *gtt = (void *)ttm;
- bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
+ struct amdgpu_device *adev;
if (gtt && gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
@@ -1042,7 +1055,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
return;
}
- if (slave)
+ if (ttm->sg && !gtt->bo->tbo.sg) {
+ struct dma_buf_attachment *attach;
+
+ attach = gtt->bo->gem_base.import_attach;
+ dma_buf_unmap_attachment(attach, ttm->sg, DMA_BIDIRECTIONAL);
+ ttm->sg = NULL;
+ return;
+ }
+
+ if (ttm->page_flags & TTM_PAGE_FLAG_SG)
return;
adev = amdgpu_ttm_adev(ttm->bdev);
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
` (3 preceding siblings ...)
2018-04-11 13:39 ` [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3 Christian König
@ 2018-04-25 23:33 ` kbuild test robot
2018-04-26 6:44 ` kbuild test robot
5 siblings, 0 replies; 8+ messages in thread
From: kbuild test robot @ 2018-04-25 23:33 UTC (permalink / raw)
To: Christian König
Cc: kbuild-all, linaro-mm-sig, linux-media, dri-devel, amd-gfx
[-- Attachment #1: Type: text/plain, Size: 3514 bytes --]
Hi Christian,
I love your patch! Yet something to improve:
[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc2 next-20180424]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Christian-K-nig/dma-buf-use-parameter-structure-for-dma_buf_attach/20180413-080639
base: git://people.freedesktop.org/~airlied/linux.git drm-next
config: powerpc64-allmodconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc64
All errors (new ones prefixed by >>):
drivers/staging/media/tegra-vde/tegra-vde.c: In function 'tegra_vde_attach_dmabuf':
>> drivers/staging/media/tegra-vde/tegra-vde.c:534:13: error: 'dmabuf' undeclared (first use in this function); did you mean 'dma_buf'?
.dmabuf = dmabuf
^~~~~~
dma_buf
drivers/staging/media/tegra-vde/tegra-vde.c:534:13: note: each undeclared identifier is reported only once for each function it appears in
vim +534 drivers/staging/media/tegra-vde/tegra-vde.c
521
522 static int tegra_vde_attach_dmabuf(struct device *dev,
523 int fd,
524 unsigned long offset,
525 unsigned int min_size,
526 struct dma_buf_attachment **a,
527 dma_addr_t *addr,
528 struct sg_table **s,
529 size_t *size,
530 enum dma_data_direction dma_dir)
531 {
532 struct dma_buf_attach_info attach_info = {
533 .dev = dev,
> 534 .dmabuf = dmabuf
535 };
536 struct dma_buf_attachment *attachment;
537 struct dma_buf *dmabuf;
538 struct sg_table *sgt;
539 int err;
540
541 dmabuf = dma_buf_get(fd);
542 if (IS_ERR(dmabuf)) {
543 dev_err(dev, "Invalid dmabuf FD\n");
544 return PTR_ERR(dmabuf);
545 }
546
547 if ((u64)offset + min_size > dmabuf->size) {
548 dev_err(dev, "Too small dmabuf size %zu @0x%lX, "
549 "should be at least %d\n",
550 dmabuf->size, offset, min_size);
551 return -EINVAL;
552 }
553
554 attachment = dma_buf_attach(&attach_info);
555 if (IS_ERR(attachment)) {
556 dev_err(dev, "Failed to attach dmabuf\n");
557 err = PTR_ERR(attachment);
558 goto err_put;
559 }
560
561 sgt = dma_buf_map_attachment(attachment, dma_dir);
562 if (IS_ERR(sgt)) {
563 dev_err(dev, "Failed to get dmabufs sg_table\n");
564 err = PTR_ERR(sgt);
565 goto err_detach;
566 }
567
568 if (sgt->nents != 1) {
569 dev_err(dev, "Sparse DMA region is unsupported\n");
570 err = -EINVAL;
571 goto err_unmap;
572 }
573
574 *addr = sg_dma_address(sgt->sgl) + offset;
575 *a = attachment;
576 *s = sgt;
577
578 if (size)
579 *size = dmabuf->size - offset;
580
581 return 0;
582
583 err_unmap:
584 dma_buf_unmap_attachment(attachment, sgt, dma_dir);
585 err_detach:
586 dma_buf_detach(dmabuf, attachment);
587 err_put:
588 dma_buf_put(dmabuf);
589
590 return err;
591 }
592
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56402 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
` (4 preceding siblings ...)
2018-04-25 23:33 ` [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach kbuild test robot
@ 2018-04-26 6:44 ` kbuild test robot
5 siblings, 0 replies; 8+ messages in thread
From: kbuild test robot @ 2018-04-26 6:44 UTC (permalink / raw)
To: Christian König
Cc: kbuild-all, linaro-mm-sig, linux-media, dri-devel, amd-gfx
[-- Attachment #1: Type: text/plain, Size: 3479 bytes --]
Hi Christian,
I love your patch! Yet something to improve:
[auto build test ERROR on drm/drm-next]
[also build test ERROR on v4.17-rc2 next-20180424]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Christian-K-nig/dma-buf-use-parameter-structure-for-dma_buf_attach/20180413-080639
base: git://people.freedesktop.org/~airlied/linux.git drm-next
config: openrisc-allyesconfig (attached as .config)
compiler: or1k-linux-gcc (GCC) 6.0.0 20160327 (experimental)
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=openrisc
All errors (new ones prefixed by >>):
drivers/staging//media/tegra-vde/tegra-vde.c: In function 'tegra_vde_attach_dmabuf':
>> drivers/staging//media/tegra-vde/tegra-vde.c:534:13: error: 'dmabuf' undeclared (first use in this function)
.dmabuf = dmabuf
^~~~~~
drivers/staging//media/tegra-vde/tegra-vde.c:534:13: note: each undeclared identifier is reported only once for each function it appears in
vim +/dmabuf +534 drivers/staging//media/tegra-vde/tegra-vde.c
521
522 static int tegra_vde_attach_dmabuf(struct device *dev,
523 int fd,
524 unsigned long offset,
525 unsigned int min_size,
526 struct dma_buf_attachment **a,
527 dma_addr_t *addr,
528 struct sg_table **s,
529 size_t *size,
530 enum dma_data_direction dma_dir)
531 {
532 struct dma_buf_attach_info attach_info = {
533 .dev = dev,
> 534 .dmabuf = dmabuf
535 };
536 struct dma_buf_attachment *attachment;
537 struct dma_buf *dmabuf;
538 struct sg_table *sgt;
539 int err;
540
541 dmabuf = dma_buf_get(fd);
542 if (IS_ERR(dmabuf)) {
543 dev_err(dev, "Invalid dmabuf FD\n");
544 return PTR_ERR(dmabuf);
545 }
546
547 if ((u64)offset + min_size > dmabuf->size) {
548 dev_err(dev, "Too small dmabuf size %zu @0x%lX, "
549 "should be at least %d\n",
550 dmabuf->size, offset, min_size);
551 return -EINVAL;
552 }
553
554 attachment = dma_buf_attach(&attach_info);
555 if (IS_ERR(attachment)) {
556 dev_err(dev, "Failed to attach dmabuf\n");
557 err = PTR_ERR(attachment);
558 goto err_put;
559 }
560
561 sgt = dma_buf_map_attachment(attachment, dma_dir);
562 if (IS_ERR(sgt)) {
563 dev_err(dev, "Failed to get dmabufs sg_table\n");
564 err = PTR_ERR(sgt);
565 goto err_detach;
566 }
567
568 if (sgt->nents != 1) {
569 dev_err(dev, "Sparse DMA region is unsupported\n");
570 err = -EINVAL;
571 goto err_unmap;
572 }
573
574 *addr = sg_dma_address(sgt->sgl) + offset;
575 *a = attachment;
576 *s = sgt;
577
578 if (size)
579 *size = dmabuf->size - offset;
580
581 return 0;
582
583 err_unmap:
584 dma_buf_unmap_attachment(attachment, sgt, dma_dir);
585 err_detach:
586 dma_buf_detach(dmabuf, attachment);
587 err_put:
588 dma_buf_put(dmabuf);
589
590 return err;
591 }
592
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 44655 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3
2018-03-25 10:57 [PATCH 1/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
@ 2018-03-25 10:57 ` Christian König
0 siblings, 0 replies; 8+ messages in thread
From: Christian König @ 2018-03-25 10:57 UTC (permalink / raw)
To: linaro-mm-sig, linux-media, dri-devel, amd-gfx, sumit.semwal
Instead of relying on the DRM functions just implement our own import
functions. This adds support for taking care of unpinned DMA-buf.
v2: enable for all exporters, not just amdgpu, fix invalidation
handling, lock reservation object while setting callback
v3: change to new dma_buf attach interface
Signed-off-by: Christian König <christian.koenig@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 72 ++++++++++++++++++++++++++-----
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 32 +++++++++++---
2 files changed, 89 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 7fef95f0fed1..fb43faf88eb0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -86,28 +86,24 @@ int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma
return ret;
}
-struct drm_gem_object *
-amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
- struct dma_buf_attachment *attach,
- struct sg_table *sg)
+static struct drm_gem_object *
+amdgpu_gem_prime_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
{
- struct reservation_object *resv = attach->dmabuf->resv;
+ struct reservation_object *resv = dma_buf->resv;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_bo *bo;
int ret;
ww_mutex_lock(&resv->lock, NULL);
- ret = amdgpu_bo_create(adev, attach->dmabuf->size, PAGE_SIZE,
+ ret = amdgpu_bo_create(adev, dma_buf->size, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_CPU, 0, ttm_bo_type_sg,
resv, &bo);
if (ret)
goto error;
- bo->tbo.sg = sg;
- bo->tbo.ttm->sg = sg;
bo->allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
bo->preferred_domains = AMDGPU_GEM_DOMAIN_GTT;
- if (attach->dmabuf->ops != &amdgpu_dmabuf_ops)
+ if (dma_buf->ops != &amdgpu_dmabuf_ops)
bo->prime_shared_count = 1;
ww_mutex_unlock(&resv->lock);
@@ -118,6 +114,26 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
return ERR_PTR(ret);
}
+struct drm_gem_object *
+amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
+ struct dma_buf_attachment *attach,
+ struct sg_table *sg)
+{
+ struct drm_gem_object *obj;
+ struct amdgpu_bo *bo;
+
+ obj = amdgpu_gem_prime_create_obj(dev, attach->dmabuf);
+ if (IS_ERR(obj))
+ return obj;
+
+ bo = gem_to_amdgpu_bo(obj);
+ amdgpu_bo_reserve(bo, true);
+ bo->tbo.sg = sg;
+ bo->tbo.ttm->sg = sg;
+ amdgpu_bo_unreserve(bo);
+ return obj;
+}
+
static struct sg_table *
amdgpu_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
@@ -293,9 +309,29 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
return buf;
}
+static void
+amdgpu_gem_prime_invalidate_mappings(struct dma_buf_attachment *attach)
+{
+ struct ttm_operation_ctx ctx = { false, false };
+ struct drm_gem_object *obj = attach->priv;
+ struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+ struct ttm_placement placement = {};
+ int r;
+
+ r = ttm_bo_validate(&bo->tbo, &placement, &ctx);
+ if (r)
+ DRM_ERROR("Failed to unmap DMA-buf import (%d))\n", r);
+}
+
struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
+ struct dma_buf_attach_info attach_info = {
+ .dev = dev->dev,
+ .dmabuf = dma_buf,
+ .invalidate = amdgpu_gem_prime_invalidate_mappings
+ };
+ struct dma_buf_attachment *attach;
struct drm_gem_object *obj;
if (dma_buf->ops == &amdgpu_dmabuf_ops) {
@@ -310,5 +346,21 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
}
}
- return drm_gem_prime_import(dev, dma_buf);
+ if (!dma_buf->invalidation_supported)
+ return drm_gem_prime_import(dev, dma_buf);
+
+ obj = amdgpu_gem_prime_create_obj(dev, dma_buf);
+ if (IS_ERR(obj))
+ return obj;
+
+ attach_info.priv = obj;
+ attach = dma_buf_attach(&attach_info);
+ if (IS_ERR(attach)) {
+ drm_gem_object_put(obj);
+ return ERR_CAST(attach);
+ }
+
+ get_dma_buf(dma_buf);
+ obj->import_attach = attach;
+ return obj;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index d2ab40494a4c..ad93f201e7b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -43,6 +43,7 @@
#include <linux/pagemap.h>
#include <linux/debugfs.h>
#include <linux/iommu.h>
+#include <linux/dma-buf.h>
#include "amdgpu.h"
#include "amdgpu_object.h"
#include "amdgpu_trace.h"
@@ -685,6 +686,7 @@ struct amdgpu_ttm_gup_task_list {
struct amdgpu_ttm_tt {
struct ttm_dma_tt ttm;
+ struct amdgpu_bo *bo;
u64 offset;
uint64_t userptr;
struct mm_struct *usermm;
@@ -993,6 +995,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
return NULL;
}
gtt->ttm.ttm.func = &amdgpu_backend_func;
+ gtt->bo = ttm_to_amdgpu_bo(bo);
if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) {
kfree(gtt);
return NULL;
@@ -1005,7 +1008,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
{
struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
struct amdgpu_ttm_tt *gtt = (void *)ttm;
- bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
if (gtt && gtt->userptr) {
ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
@@ -1017,7 +1019,19 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
return 0;
}
- if (slave && ttm->sg) {
+ if (ttm->page_flags & TTM_PAGE_FLAG_SG) {
+ if (!ttm->sg) {
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+
+ attach = gtt->bo->gem_base.import_attach;
+ sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR(sgt))
+ return PTR_ERR(sgt);
+
+ ttm->sg = sgt;
+ }
+
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
gtt->ttm.dma_address,
ttm->num_pages);
@@ -1036,9 +1050,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm,
static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
{
- struct amdgpu_device *adev;
struct amdgpu_ttm_tt *gtt = (void *)ttm;
- bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
+ struct amdgpu_device *adev;
if (gtt && gtt->userptr) {
amdgpu_ttm_tt_set_user_pages(ttm, NULL);
@@ -1047,7 +1060,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
return;
}
- if (slave)
+ if (ttm->sg && !gtt->bo->tbo.sg) {
+ struct dma_buf_attachment *attach;
+
+ attach = gtt->bo->gem_base.import_attach;
+ dma_buf_unmap_attachment(attach, ttm->sg, DMA_BIDIRECTIONAL);
+ ttm->sg = NULL;
+ return;
+ }
+
+ if (ttm->page_flags & TTM_PAGE_FLAG_SG)
return;
adev = amdgpu_ttm_adev(ttm->bdev);
--
2.14.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2018-04-26 6:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-11 13:39 [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach Christian König
2018-04-11 13:39 ` [PATCH 2/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
2018-04-11 13:39 ` [PATCH 3/5] drm/ttm: remove the backing store if no placement is given Christian König
2018-04-11 13:39 ` [PATCH 4/5] drm/amdgpu: add independent DMA-buf export v2 Christian König
2018-04-11 13:39 ` [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3 Christian König
2018-04-25 23:33 ` [PATCH 1/5] dma-buf: use parameter structure for dma_buf_attach kbuild test robot
2018-04-26 6:44 ` kbuild test robot
-- strict thread matches above, loose matches on Subject: below --
2018-03-25 10:57 [PATCH 1/5] dma-buf: add optional invalidate_mappings callback v3 Christian König
2018-03-25 10:57 ` [PATCH 5/5] drm/amdgpu: add independent DMA-buf import v3 Christian König
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).