All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
@ 2019-10-21 11:15 ` Christian König
  0 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

This patch is a stripped down version of the locking changes
necessary to support dynamic DMA-buf handling.

It adds a dynamic flag for both importers as well as exporters
so that drivers can choose if they want the reservation object
locked or unlocked during mapping of attachments.

For compatibility between drivers we cache the DMA-buf mapping
during attaching an importer as soon as exporter/importer
disagree on the dynamic handling.

This change has gone through a lengthy discussion on dri-devel
and other mailing lists with at least 3-4 different attempts and
dead-ends until we settled on this solution. Please refer to the
mailing lists archives for full background on the history of
this change.

v2: cleanup set_name merge, improve kerneldoc

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
 include/linux/dma-buf.h   |  57 +++++++++++++++++++--
 2 files changed, 143 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 433d91d710e4..753be84b5fd6 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
 	size_t ret = 0;
 
 	dmabuf = dentry->d_fsdata;
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (dmabuf->name)
 		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 
 	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
 			     dentry->d_name.name, ret > 0 ? name : "");
@@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
 	if (IS_ERR(name))
 		return PTR_ERR(name);
 
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (!list_empty(&dmabuf->attachments)) {
 		ret = -EBUSY;
 		kfree(name);
@@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
 	dmabuf->name = name;
 
 out_unlock:
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 	return ret;
 }
 
@@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
 	/* Don't count the temporary reference taken inside procfs seq_show */
 	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
 	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (dmabuf->name)
 		seq_printf(m, "name:\t%s\n", dmabuf->name);
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 }
 
 static const struct file_operations dma_buf_fops = {
@@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
 		return ERR_PTR(-EINVAL);
 	}
 
+	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
+		    exp_info->ops->dynamic_mapping))
+		return ERR_PTR(-EINVAL);
+
 	if (!try_module_get(exp_info->owner))
 		return ERR_PTR(-ENOENT);
 
@@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
 EXPORT_SYMBOL_GPL(dma_buf_put);
 
 /**
- * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
+ * dma_buf_dynamic_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.
+ * @dmabuf:		[in]	buffer to attach device to.
+ * @dev:		[in]	device to be attached.
+ * @dynamic_mapping:	[in]	calling convention for map/unmap
  *
  * Returns struct dma_buf_attachment pointer for this attachment. Attachments
  * must be cleaned up by calling dma_buf_detach().
@@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+		       bool dynamic_mapping)
 {
 	struct dma_buf_attachment *attach;
 	int ret;
@@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 
 	attach->dev = dev;
 	attach->dmabuf = dmabuf;
+	attach->dynamic_mapping = dynamic_mapping;
 
 	mutex_lock(&dmabuf->lock);
 
@@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 		if (ret)
 			goto err_attach;
 	}
+	dma_resv_lock(dmabuf->resv, NULL);
 	list_add(&attach->node, &dmabuf->attachments);
+	dma_resv_unlock(dmabuf->resv);
 
 	mutex_unlock(&dmabuf->lock);
 
+	/* When either the importer or the exporter can't handle dynamic
+	 * mappings we cache the mapping here to avoid issues with the
+	 * reservation object lock.
+	 */
+	if (dma_buf_attachment_is_dynamic(attach) !=
+	    dma_buf_is_dynamic(dmabuf)) {
+		struct sg_table *sgt;
+
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_lock(attach->dmabuf->resv, NULL);
+
+		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
+		if (!sgt)
+			sgt = ERR_PTR(-ENOMEM);
+		if (IS_ERR(sgt)) {
+			ret = PTR_ERR(sgt);
+			goto err_unlock;
+		}
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_unlock(attach->dmabuf->resv);
+		attach->sgt = sgt;
+		attach->dir = DMA_BIDIRECTIONAL;
+	}
+
 	return attach;
 
 err_attach:
 	kfree(attach);
 	mutex_unlock(&dmabuf->lock);
 	return ERR_PTR(ret);
+
+err_unlock:
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_unlock(attach->dmabuf->resv);
+
+	dma_buf_detach(dmabuf, attach);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
+
+/**
+ * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
+ * @dmabuf:	[in]	buffer to attach device to.
+ * @dev:	[in]	device to be attached.
+ *
+ * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
+ * mapping.
+ */
+struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
+					  struct device *dev)
+{
+	return dma_buf_dynamic_attach(dmabuf, dev, false);
 }
 EXPORT_SYMBOL_GPL(dma_buf_attach);
 
@@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 	if (WARN_ON(!dmabuf || !attach))
 		return;
 
-	if (attach->sgt)
+	if (attach->sgt) {
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_lock(attach->dmabuf->resv, NULL);
+
 		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
 
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_unlock(attach->dmabuf->resv);
+	}
+
 	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	list_del(&attach->node);
+	dma_resv_unlock(dmabuf->resv);
 	if (dmabuf->ops->detach)
 		dmabuf->ops->detach(dmabuf, attach);
 
@@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 	if (WARN_ON(!attach || !attach->dmabuf))
 		return ERR_PTR(-EINVAL);
 
+	if (dma_buf_attachment_is_dynamic(attach))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	if (attach->sgt) {
 		/*
 		 * Two mappings with different directions for the same
@@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 		return attach->sgt;
 	}
 
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
 	if (!sg_table)
 		sg_table = ERR_PTR(-ENOMEM);
@@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
 	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
 		return;
 
+	if (dma_buf_attachment_is_dynamic(attach))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	if (attach->sgt == sg_table)
 		return;
 
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
@@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		seq_puts(s, "\tAttached Devices:\n");
 		attach_count = 0;
 
+		dma_resv_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++;
 		}
+		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -42,6 +42,18 @@ struct dma_buf_ops {
 	  */
 	bool cache_sgt_mapping;
 
+	/**
+	 * @dynamic_mapping:
+	 *
+	 * If true the framework makes sure that the map/unmap_dma_buf
+	 * callbacks are always called with the dma_resv object locked.
+	 *
+	 * If false the framework makes ure that the map/unmap_dma_buf
+	 * callbacks are always called without the dma_resv object locked.
+	 * Mutual exclusive with @cache_sgt_mapping.
+	 */
+	bool dynamic_mapping;
+
 	/**
 	 * @attach:
 	 *
@@ -109,6 +121,9 @@ struct dma_buf_ops {
 	 * any other kind of sharing that the exporter might wish to make
 	 * available to buffer-users.
 	 *
+	 * This is always called with the dmabuf->resv object locked when
+	 * the dynamic_mapping flag is true.
+	 *
 	 * Returns:
 	 *
 	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
@@ -267,7 +282,8 @@ struct dma_buf_ops {
  * struct dma_buf - shared buffer object
  * @size: size of the buffer
  * @file: file pointer used for sharing buffers across, and for refcounting.
- * @attachments: list of dma_buf_attachment that denotes all devices attached.
+ * @attachments: list of dma_buf_attachment that denotes all devices attached,
+ *               protected by dma_resv lock.
  * @ops: dma_buf_ops associated with this buffer object.
  * @lock: used internally to serialize list manipulation, attach/detach and
  *        vmap/unmap, and accesses to name
@@ -323,10 +339,12 @@ struct dma_buf {
  * struct dma_buf_attachment - holds device-buffer attachment data
  * @dmabuf: buffer for this attachment.
  * @dev: device attached to the buffer.
- * @node: list of dma_buf_attachment.
+ * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
  * @sgt: cached mapping.
  * @dir: direction of cached mapping.
  * @priv: exporter specific attachment data.
+ * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
+ * dma_resv lock held.
  *
  * This structure holds the attachment information between the dma_buf buffer
  * and its user device(s). The list contains one attachment struct per device
@@ -343,6 +361,7 @@ struct dma_buf_attachment {
 	struct list_head node;
 	struct sg_table *sgt;
 	enum dma_data_direction dir;
+	bool dynamic_mapping;
 	void *priv;
 };
 
@@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
 	get_file(dmabuf->file);
 }
 
+/**
+ * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
+ * @dmabuf: the DMA-buf to check
+ *
+ * Returns true if a DMA-buf exporter wants to be called with the dma_resv
+ * locked, false if it doesn't wants to be called with the lock held.
+ */
+static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
+{
+	return dmabuf->ops->dynamic_mapping;
+}
+
+/**
+ * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
+ * mappinsg
+ * @attach: the DMA-buf attachment to check
+ *
+ * Returns true if a DMA-buf importer wants to call the map/unmap functions with
+ * the dma_resv lock held.
+ */
+static inline bool
+dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
+{
+	return attach->dynamic_mapping;
+}
+
 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
-							struct device *dev);
+					  struct device *dev);
+struct dma_buf_attachment *
+dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+		       bool dynamic_mapping);
 void dma_buf_detach(struct dma_buf *dmabuf,
-				struct dma_buf_attachment *dmabuf_attach);
+		    struct dma_buf_attachment *attach);
 
 struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
 
@@ -409,6 +457,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_move_notify(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.17.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
@ 2019-10-21 11:15 ` Christian König
  0 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

This patch is a stripped down version of the locking changes
necessary to support dynamic DMA-buf handling.

It adds a dynamic flag for both importers as well as exporters
so that drivers can choose if they want the reservation object
locked or unlocked during mapping of attachments.

For compatibility between drivers we cache the DMA-buf mapping
during attaching an importer as soon as exporter/importer
disagree on the dynamic handling.

This change has gone through a lengthy discussion on dri-devel
and other mailing lists with at least 3-4 different attempts and
dead-ends until we settled on this solution. Please refer to the
mailing lists archives for full background on the history of
this change.

v2: cleanup set_name merge, improve kerneldoc

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
 include/linux/dma-buf.h   |  57 +++++++++++++++++++--
 2 files changed, 143 insertions(+), 16 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 433d91d710e4..753be84b5fd6 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
 	size_t ret = 0;
 
 	dmabuf = dentry->d_fsdata;
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (dmabuf->name)
 		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 
 	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
 			     dentry->d_name.name, ret > 0 ? name : "");
@@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
 	if (IS_ERR(name))
 		return PTR_ERR(name);
 
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (!list_empty(&dmabuf->attachments)) {
 		ret = -EBUSY;
 		kfree(name);
@@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
 	dmabuf->name = name;
 
 out_unlock:
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 	return ret;
 }
 
@@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
 	/* Don't count the temporary reference taken inside procfs seq_show */
 	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
 	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
-	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	if (dmabuf->name)
 		seq_printf(m, "name:\t%s\n", dmabuf->name);
-	mutex_unlock(&dmabuf->lock);
+	dma_resv_unlock(dmabuf->resv);
 }
 
 static const struct file_operations dma_buf_fops = {
@@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
 		return ERR_PTR(-EINVAL);
 	}
 
+	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
+		    exp_info->ops->dynamic_mapping))
+		return ERR_PTR(-EINVAL);
+
 	if (!try_module_get(exp_info->owner))
 		return ERR_PTR(-ENOENT);
 
@@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
 EXPORT_SYMBOL_GPL(dma_buf_put);
 
 /**
- * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
+ * dma_buf_dynamic_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.
+ * @dmabuf:		[in]	buffer to attach device to.
+ * @dev:		[in]	device to be attached.
+ * @dynamic_mapping:	[in]	calling convention for map/unmap
  *
  * Returns struct dma_buf_attachment pointer for this attachment. Attachments
  * must be cleaned up by calling dma_buf_detach().
@@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+		       bool dynamic_mapping)
 {
 	struct dma_buf_attachment *attach;
 	int ret;
@@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 
 	attach->dev = dev;
 	attach->dmabuf = dmabuf;
+	attach->dynamic_mapping = dynamic_mapping;
 
 	mutex_lock(&dmabuf->lock);
 
@@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 		if (ret)
 			goto err_attach;
 	}
+	dma_resv_lock(dmabuf->resv, NULL);
 	list_add(&attach->node, &dmabuf->attachments);
+	dma_resv_unlock(dmabuf->resv);
 
 	mutex_unlock(&dmabuf->lock);
 
+	/* When either the importer or the exporter can't handle dynamic
+	 * mappings we cache the mapping here to avoid issues with the
+	 * reservation object lock.
+	 */
+	if (dma_buf_attachment_is_dynamic(attach) !=
+	    dma_buf_is_dynamic(dmabuf)) {
+		struct sg_table *sgt;
+
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_lock(attach->dmabuf->resv, NULL);
+
+		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
+		if (!sgt)
+			sgt = ERR_PTR(-ENOMEM);
+		if (IS_ERR(sgt)) {
+			ret = PTR_ERR(sgt);
+			goto err_unlock;
+		}
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_unlock(attach->dmabuf->resv);
+		attach->sgt = sgt;
+		attach->dir = DMA_BIDIRECTIONAL;
+	}
+
 	return attach;
 
 err_attach:
 	kfree(attach);
 	mutex_unlock(&dmabuf->lock);
 	return ERR_PTR(ret);
+
+err_unlock:
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_unlock(attach->dmabuf->resv);
+
+	dma_buf_detach(dmabuf, attach);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
+
+/**
+ * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
+ * @dmabuf:	[in]	buffer to attach device to.
+ * @dev:	[in]	device to be attached.
+ *
+ * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
+ * mapping.
+ */
+struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
+					  struct device *dev)
+{
+	return dma_buf_dynamic_attach(dmabuf, dev, false);
 }
 EXPORT_SYMBOL_GPL(dma_buf_attach);
 
@@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 	if (WARN_ON(!dmabuf || !attach))
 		return;
 
-	if (attach->sgt)
+	if (attach->sgt) {
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_lock(attach->dmabuf->resv, NULL);
+
 		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
 
+		if (dma_buf_is_dynamic(attach->dmabuf))
+			dma_resv_unlock(attach->dmabuf->resv);
+	}
+
 	mutex_lock(&dmabuf->lock);
+	dma_resv_lock(dmabuf->resv, NULL);
 	list_del(&attach->node);
+	dma_resv_unlock(dmabuf->resv);
 	if (dmabuf->ops->detach)
 		dmabuf->ops->detach(dmabuf, attach);
 
@@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 	if (WARN_ON(!attach || !attach->dmabuf))
 		return ERR_PTR(-EINVAL);
 
+	if (dma_buf_attachment_is_dynamic(attach))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	if (attach->sgt) {
 		/*
 		 * Two mappings with different directions for the same
@@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 		return attach->sgt;
 	}
 
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
 	if (!sg_table)
 		sg_table = ERR_PTR(-ENOMEM);
@@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
 	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
 		return;
 
+	if (dma_buf_attachment_is_dynamic(attach))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	if (attach->sgt == sg_table)
 		return;
 
+	if (dma_buf_is_dynamic(attach->dmabuf))
+		dma_resv_assert_held(attach->dmabuf->resv);
+
 	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
 }
 EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
@@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		seq_puts(s, "\tAttached Devices:\n");
 		attach_count = 0;
 
+		dma_resv_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++;
 		}
+		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -42,6 +42,18 @@ struct dma_buf_ops {
 	  */
 	bool cache_sgt_mapping;
 
+	/**
+	 * @dynamic_mapping:
+	 *
+	 * If true the framework makes sure that the map/unmap_dma_buf
+	 * callbacks are always called with the dma_resv object locked.
+	 *
+	 * If false the framework makes ure that the map/unmap_dma_buf
+	 * callbacks are always called without the dma_resv object locked.
+	 * Mutual exclusive with @cache_sgt_mapping.
+	 */
+	bool dynamic_mapping;
+
 	/**
 	 * @attach:
 	 *
@@ -109,6 +121,9 @@ struct dma_buf_ops {
 	 * any other kind of sharing that the exporter might wish to make
 	 * available to buffer-users.
 	 *
+	 * This is always called with the dmabuf->resv object locked when
+	 * the dynamic_mapping flag is true.
+	 *
 	 * Returns:
 	 *
 	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
@@ -267,7 +282,8 @@ struct dma_buf_ops {
  * struct dma_buf - shared buffer object
  * @size: size of the buffer
  * @file: file pointer used for sharing buffers across, and for refcounting.
- * @attachments: list of dma_buf_attachment that denotes all devices attached.
+ * @attachments: list of dma_buf_attachment that denotes all devices attached,
+ *               protected by dma_resv lock.
  * @ops: dma_buf_ops associated with this buffer object.
  * @lock: used internally to serialize list manipulation, attach/detach and
  *        vmap/unmap, and accesses to name
@@ -323,10 +339,12 @@ struct dma_buf {
  * struct dma_buf_attachment - holds device-buffer attachment data
  * @dmabuf: buffer for this attachment.
  * @dev: device attached to the buffer.
- * @node: list of dma_buf_attachment.
+ * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
  * @sgt: cached mapping.
  * @dir: direction of cached mapping.
  * @priv: exporter specific attachment data.
+ * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
+ * dma_resv lock held.
  *
  * This structure holds the attachment information between the dma_buf buffer
  * and its user device(s). The list contains one attachment struct per device
@@ -343,6 +361,7 @@ struct dma_buf_attachment {
 	struct list_head node;
 	struct sg_table *sgt;
 	enum dma_data_direction dir;
+	bool dynamic_mapping;
 	void *priv;
 };
 
@@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
 	get_file(dmabuf->file);
 }
 
+/**
+ * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
+ * @dmabuf: the DMA-buf to check
+ *
+ * Returns true if a DMA-buf exporter wants to be called with the dma_resv
+ * locked, false if it doesn't wants to be called with the lock held.
+ */
+static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
+{
+	return dmabuf->ops->dynamic_mapping;
+}
+
+/**
+ * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
+ * mappinsg
+ * @attach: the DMA-buf attachment to check
+ *
+ * Returns true if a DMA-buf importer wants to call the map/unmap functions with
+ * the dma_resv lock held.
+ */
+static inline bool
+dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
+{
+	return attach->dynamic_mapping;
+}
+
 struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
-							struct device *dev);
+					  struct device *dev);
+struct dma_buf_attachment *
+dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
+		       bool dynamic_mapping);
 void dma_buf_detach(struct dma_buf *dmabuf,
-				struct dma_buf_attachment *dmabuf_attach);
+		    struct dma_buf_attachment *attach);
 
 struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
 
@@ -409,6 +457,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_move_notify(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.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/4] dma-buf: stop using the dmabuf->lock so much
  2019-10-21 11:15 ` Christian König
@ 2019-10-21 11:15   ` Christian König
  -1 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

The attachment list is now protected by the dma_resv object.
So we can drop holding this lock to allow concurrent attach
and detach operations.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 753be84b5fd6..c736e67ae1a1 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -685,8 +685,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 	attach->dmabuf = dmabuf;
 	attach->dynamic_mapping = dynamic_mapping;
 
-	mutex_lock(&dmabuf->lock);
-
 	if (dmabuf->ops->attach) {
 		ret = dmabuf->ops->attach(dmabuf, attach);
 		if (ret)
@@ -696,8 +694,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 	list_add(&attach->node, &dmabuf->attachments);
 	dma_resv_unlock(dmabuf->resv);
 
-	mutex_unlock(&dmabuf->lock);
-
 	/* When either the importer or the exporter can't handle dynamic
 	 * mappings we cache the mapping here to avoid issues with the
 	 * reservation object lock.
@@ -726,7 +722,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 
 err_attach:
 	kfree(attach);
-	mutex_unlock(&dmabuf->lock);
 	return ERR_PTR(ret);
 
 err_unlock:
@@ -776,14 +771,12 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 			dma_resv_unlock(attach->dmabuf->resv);
 	}
 
-	mutex_lock(&dmabuf->lock);
 	dma_resv_lock(dmabuf->resv, NULL);
 	list_del(&attach->node);
 	dma_resv_unlock(dmabuf->resv);
 	if (dmabuf->ops->detach)
 		dmabuf->ops->detach(dmabuf, attach);
 
-	mutex_unlock(&dmabuf->lock);
 	kfree(attach);
 }
 EXPORT_SYMBOL_GPL(dma_buf_detach);
@@ -1247,14 +1240,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		   "size", "flags", "mode", "count", "ino");
 
 	list_for_each_entry(buf_obj, &db_list.head, list_node) {
-		ret = mutex_lock_interruptible(&buf_obj->lock);
-
-		if (ret) {
-			seq_puts(s,
-				 "\tERROR locking buffer object: skipping\n");
-			continue;
-		}
-
 		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
 				buf_obj->size,
 				buf_obj->file->f_flags, buf_obj->file->f_mode,
@@ -1307,7 +1292,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 
 		count++;
 		size += buf_obj->size;
-		mutex_unlock(&buf_obj->lock);
 	}
 
 	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/4] dma-buf: stop using the dmabuf->lock so much
@ 2019-10-21 11:15   ` Christian König
  0 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

The attachment list is now protected by the dma_resv object.
So we can drop holding this lock to allow concurrent attach
and detach operations.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 753be84b5fd6..c736e67ae1a1 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -685,8 +685,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 	attach->dmabuf = dmabuf;
 	attach->dynamic_mapping = dynamic_mapping;
 
-	mutex_lock(&dmabuf->lock);
-
 	if (dmabuf->ops->attach) {
 		ret = dmabuf->ops->attach(dmabuf, attach);
 		if (ret)
@@ -696,8 +694,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 	list_add(&attach->node, &dmabuf->attachments);
 	dma_resv_unlock(dmabuf->resv);
 
-	mutex_unlock(&dmabuf->lock);
-
 	/* When either the importer or the exporter can't handle dynamic
 	 * mappings we cache the mapping here to avoid issues with the
 	 * reservation object lock.
@@ -726,7 +722,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 
 err_attach:
 	kfree(attach);
-	mutex_unlock(&dmabuf->lock);
 	return ERR_PTR(ret);
 
 err_unlock:
@@ -776,14 +771,12 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
 			dma_resv_unlock(attach->dmabuf->resv);
 	}
 
-	mutex_lock(&dmabuf->lock);
 	dma_resv_lock(dmabuf->resv, NULL);
 	list_del(&attach->node);
 	dma_resv_unlock(dmabuf->resv);
 	if (dmabuf->ops->detach)
 		dmabuf->ops->detach(dmabuf, attach);
 
-	mutex_unlock(&dmabuf->lock);
 	kfree(attach);
 }
 EXPORT_SYMBOL_GPL(dma_buf_detach);
@@ -1247,14 +1240,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		   "size", "flags", "mode", "count", "ino");
 
 	list_for_each_entry(buf_obj, &db_list.head, list_node) {
-		ret = mutex_lock_interruptible(&buf_obj->lock);
-
-		if (ret) {
-			seq_puts(s,
-				 "\tERROR locking buffer object: skipping\n");
-			continue;
-		}
-
 		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
 				buf_obj->size,
 				buf_obj->file->f_flags, buf_obj->file->f_mode,
@@ -1307,7 +1292,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 
 		count++;
 		size += buf_obj->size;
-		mutex_unlock(&buf_obj->lock);
 	}
 
 	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/4] drm/amdgpu: add independent DMA-buf export v7
  2019-10-21 11:15 ` Christian König
@ 2019-10-21 11:15   ` Christian König
  -1 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

Add an DMA-buf export implementation independent of the DRM helpers.

This not only avoids the caching of DMA-buf mappings, but also
allows us to use the new dynamic locking approach.

This is also a prerequisite of unpinned DMA-buf handling.

v2: fix unintended recursion, remove debugging leftovers
v3: split out from unpinned DMA-buf work
v4: rebase on top of new no_sgt_cache flag
v5: fix some warnings by including amdgpu_dma_buf.h
v6: fix locking for non amdgpu exports
v7: rebased on new DMA-buf locking patch

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 172 +++++++++++---------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h |   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c     |   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c  |   1 +
 4 files changed, 97 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 61f108ec2b5c..f14b52cc7205 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -34,26 +34,11 @@
 #include "amdgpu.h"
 #include "amdgpu_display.h"
 #include "amdgpu_gem.h"
+#include "amdgpu_dma_buf.h"
 #include <drm/amdgpu_drm.h>
 #include <linux/dma-buf.h>
 #include <linux/dma-fence-array.h>
 
-/**
- * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
- * implementation
- * @obj: GEM buffer object (BO)
- *
- * Returns:
- * A scatter/gather table for the pinned pages of the BO's memory.
- */
-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);
-}
-
 /**
  * amdgpu_gem_prime_vmap - &dma_buf_ops.vmap implementation
  * @obj: GEM BO
@@ -179,92 +164,126 @@ __dma_resv_make_exclusive(struct dma_resv *obj)
 }
 
 /**
- * amdgpu_dma_buf_map_attach - &dma_buf_ops.attach implementation
- * @dma_buf: Shared DMA buffer
+ * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
+ *
+ * @dmabuf: DMA-buf where we attach to
+ * @attach: attachment to add
+ *
+ * Add the attachment as user to the exported DMA-buf.
+ */
+static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
+				 struct dma_buf_attachment *attach)
+{
+	struct drm_gem_object *obj = dmabuf->priv;
+	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+	int r;
+
+	if (attach->dev->driver == adev->dev->driver)
+		return 0;
+
+	r = amdgpu_bo_reserve(bo, false);
+	if (unlikely(r != 0))
+		return r;
+
+	/*
+	 * We only create shared fences for internal use, but importers
+	 * of the dmabuf rely on exclusive fences for implicitly
+	 * tracking write hazards. As any of the current fences may
+	 * correspond to a write, we need to convert all existing
+	 * fences on the reservation object into a single exclusive
+	 * fence.
+	 */
+	r = __dma_resv_make_exclusive(bo->tbo.base.resv);
+	if (r)
+		return r;
+
+	bo->prime_shared_count++;
+	amdgpu_bo_unreserve(bo);
+	return 0;
+}
+
+/**
+ * amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
+ *
+ * @dmabuf: DMA-buf where we remove the attachment from
+ * @attach: the attachment to remove
+ *
+ * Called when an attachment is removed from the DMA-buf.
+ */
+static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
+				  struct dma_buf_attachment *attach)
+{
+	struct drm_gem_object *obj = dmabuf->priv;
+	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+
+	if (attach->dev->driver != adev->dev->driver && bo->prime_shared_count)
+		bo->prime_shared_count--;
+}
+
+/**
+ * amdgpu_dma_buf_map - &dma_buf_ops.map_dma_buf implementation
  * @attach: DMA-buf attachment
+ * @dir: DMA direction
  *
  * Makes sure that the shared DMA buffer can be accessed by the target device.
  * For now, simply pins it to the GTT domain, where it should be accessible by
  * all DMA devices.
  *
  * Returns:
- * 0 on success or a negative error code on failure.
+ * sg_table filled with the DMA addresses to use or ERR_PRT with negative error
+ * code.
  */
-static int amdgpu_dma_buf_map_attach(struct dma_buf *dma_buf,
-				     struct dma_buf_attachment *attach)
+static struct sg_table *amdgpu_dma_buf_map(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, attach);
-	if (r)
-		return r;
-
-	r = amdgpu_bo_reserve(bo, false);
-	if (unlikely(r != 0))
-		goto error_detach;
-
-
-	if (attach->dev->driver != adev->dev->driver) {
-		/*
-		 * We only create shared fences for internal use, but importers
-		 * of the dmabuf rely on exclusive fences for implicitly
-		 * tracking write hazards. As any of the current fences may
-		 * correspond to a write, we need to convert all existing
-		 * fences on the reservation object into a single exclusive
-		 * fence.
-		 */
-		r = __dma_resv_make_exclusive(bo->tbo.base.resv);
-		if (r)
-			goto error_unreserve;
-	}
-
-	/* pin buffer into GTT */
 	r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
 	if (r)
-		goto error_unreserve;
+		return ERR_PTR(r);
 
-	if (attach->dev->driver != adev->dev->driver)
-		bo->prime_shared_count++;
+	sgt = drm_prime_pages_to_sg(bo->tbo.ttm->pages, bo->tbo.num_pages);
+	if (IS_ERR(sgt))
+		return sgt;
 
-error_unreserve:
-	amdgpu_bo_unreserve(bo);
+	if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+			      DMA_ATTR_SKIP_CPU_SYNC))
+		goto error_free;
 
-error_detach:
-	if (r)
-		drm_gem_map_detach(dma_buf, attach);
-	return r;
+	return sgt;
+
+error_free:
+	sg_free_table(sgt);
+	kfree(sgt);
+	return ERR_PTR(-ENOMEM);
 }
 
 /**
- * amdgpu_dma_buf_map_detach - &dma_buf_ops.detach implementation
- * @dma_buf: Shared DMA buffer
+ * amdgpu_dma_buf_unmap - &dma_buf_ops.unmap_dma_buf implementation
  * @attach: DMA-buf attachment
+ * @sgt: sg_table to unmap
+ * @dir: DMA direction
  *
  * This is called when a shared DMA buffer no longer needs to be accessible by
  * another device. For now, simply unpins the buffer from GTT.
  */
-static void amdgpu_dma_buf_map_detach(struct dma_buf *dma_buf,
-				      struct dma_buf_attachment *attach)
+static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
+				 struct sg_table *sgt,
+				 enum dma_data_direction dir)
 {
-	struct drm_gem_object *obj = dma_buf->priv;
+	struct drm_gem_object *obj = attach->dmabuf->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;
 
+	dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+	sg_free_table(sgt);
+	kfree(sgt);
 	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);
 }
 
 /**
@@ -308,10 +327,11 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 }
 
 const struct dma_buf_ops amdgpu_dmabuf_ops = {
-	.attach = amdgpu_dma_buf_map_attach,
-	.detach = amdgpu_dma_buf_map_detach,
-	.map_dma_buf = drm_gem_map_dma_buf,
-	.unmap_dma_buf = drm_gem_unmap_dma_buf,
+	.dynamic_mapping = true,
+	.attach = amdgpu_dma_buf_attach,
+	.detach = amdgpu_dma_buf_detach,
+	.map_dma_buf = amdgpu_dma_buf_map,
+	.unmap_dma_buf = amdgpu_dma_buf_unmap,
 	.release = drm_gem_dmabuf_release,
 	.begin_cpu_access = amdgpu_dma_buf_begin_cpu_access,
 	.mmap = drm_gem_dmabuf_mmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
index 5012e6ab58f1..ce1b3f017451 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
@@ -25,7 +25,6 @@
 
 #include <drm/drm_gem.h>
 
-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 3fae1007143e..bf5bf15b12e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1409,7 +1409,6 @@ static struct drm_driver kms_driver = {
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_export = amdgpu_gem_prime_export,
 	.gem_prime_import = amdgpu_gem_prime_import,
-	.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 6f0b789a0b49..b319254537b8 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/amdgpu_drm.h>
 #include <drm/drm_cache.h>
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/4] drm/amdgpu: add independent DMA-buf export v7
@ 2019-10-21 11:15   ` Christian König
  0 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

Add an DMA-buf export implementation independent of the DRM helpers.

This not only avoids the caching of DMA-buf mappings, but also
allows us to use the new dynamic locking approach.

This is also a prerequisite of unpinned DMA-buf handling.

v2: fix unintended recursion, remove debugging leftovers
v3: split out from unpinned DMA-buf work
v4: rebase on top of new no_sgt_cache flag
v5: fix some warnings by including amdgpu_dma_buf.h
v6: fix locking for non amdgpu exports
v7: rebased on new DMA-buf locking patch

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 172 +++++++++++---------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h |   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c     |   1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c  |   1 +
 4 files changed, 97 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 61f108ec2b5c..f14b52cc7205 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -34,26 +34,11 @@
 #include "amdgpu.h"
 #include "amdgpu_display.h"
 #include "amdgpu_gem.h"
+#include "amdgpu_dma_buf.h"
 #include <drm/amdgpu_drm.h>
 #include <linux/dma-buf.h>
 #include <linux/dma-fence-array.h>
 
-/**
- * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
- * implementation
- * @obj: GEM buffer object (BO)
- *
- * Returns:
- * A scatter/gather table for the pinned pages of the BO's memory.
- */
-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);
-}
-
 /**
  * amdgpu_gem_prime_vmap - &dma_buf_ops.vmap implementation
  * @obj: GEM BO
@@ -179,92 +164,126 @@ __dma_resv_make_exclusive(struct dma_resv *obj)
 }
 
 /**
- * amdgpu_dma_buf_map_attach - &dma_buf_ops.attach implementation
- * @dma_buf: Shared DMA buffer
+ * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation
+ *
+ * @dmabuf: DMA-buf where we attach to
+ * @attach: attachment to add
+ *
+ * Add the attachment as user to the exported DMA-buf.
+ */
+static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
+				 struct dma_buf_attachment *attach)
+{
+	struct drm_gem_object *obj = dmabuf->priv;
+	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+	int r;
+
+	if (attach->dev->driver == adev->dev->driver)
+		return 0;
+
+	r = amdgpu_bo_reserve(bo, false);
+	if (unlikely(r != 0))
+		return r;
+
+	/*
+	 * We only create shared fences for internal use, but importers
+	 * of the dmabuf rely on exclusive fences for implicitly
+	 * tracking write hazards. As any of the current fences may
+	 * correspond to a write, we need to convert all existing
+	 * fences on the reservation object into a single exclusive
+	 * fence.
+	 */
+	r = __dma_resv_make_exclusive(bo->tbo.base.resv);
+	if (r)
+		return r;
+
+	bo->prime_shared_count++;
+	amdgpu_bo_unreserve(bo);
+	return 0;
+}
+
+/**
+ * amdgpu_dma_buf_detach - &dma_buf_ops.detach implementation
+ *
+ * @dmabuf: DMA-buf where we remove the attachment from
+ * @attach: the attachment to remove
+ *
+ * Called when an attachment is removed from the DMA-buf.
+ */
+static void amdgpu_dma_buf_detach(struct dma_buf *dmabuf,
+				  struct dma_buf_attachment *attach)
+{
+	struct drm_gem_object *obj = dmabuf->priv;
+	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+
+	if (attach->dev->driver != adev->dev->driver && bo->prime_shared_count)
+		bo->prime_shared_count--;
+}
+
+/**
+ * amdgpu_dma_buf_map - &dma_buf_ops.map_dma_buf implementation
  * @attach: DMA-buf attachment
+ * @dir: DMA direction
  *
  * Makes sure that the shared DMA buffer can be accessed by the target device.
  * For now, simply pins it to the GTT domain, where it should be accessible by
  * all DMA devices.
  *
  * Returns:
- * 0 on success or a negative error code on failure.
+ * sg_table filled with the DMA addresses to use or ERR_PRT with negative error
+ * code.
  */
-static int amdgpu_dma_buf_map_attach(struct dma_buf *dma_buf,
-				     struct dma_buf_attachment *attach)
+static struct sg_table *amdgpu_dma_buf_map(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, attach);
-	if (r)
-		return r;
-
-	r = amdgpu_bo_reserve(bo, false);
-	if (unlikely(r != 0))
-		goto error_detach;
-
-
-	if (attach->dev->driver != adev->dev->driver) {
-		/*
-		 * We only create shared fences for internal use, but importers
-		 * of the dmabuf rely on exclusive fences for implicitly
-		 * tracking write hazards. As any of the current fences may
-		 * correspond to a write, we need to convert all existing
-		 * fences on the reservation object into a single exclusive
-		 * fence.
-		 */
-		r = __dma_resv_make_exclusive(bo->tbo.base.resv);
-		if (r)
-			goto error_unreserve;
-	}
-
-	/* pin buffer into GTT */
 	r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
 	if (r)
-		goto error_unreserve;
+		return ERR_PTR(r);
 
-	if (attach->dev->driver != adev->dev->driver)
-		bo->prime_shared_count++;
+	sgt = drm_prime_pages_to_sg(bo->tbo.ttm->pages, bo->tbo.num_pages);
+	if (IS_ERR(sgt))
+		return sgt;
 
-error_unreserve:
-	amdgpu_bo_unreserve(bo);
+	if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
+			      DMA_ATTR_SKIP_CPU_SYNC))
+		goto error_free;
 
-error_detach:
-	if (r)
-		drm_gem_map_detach(dma_buf, attach);
-	return r;
+	return sgt;
+
+error_free:
+	sg_free_table(sgt);
+	kfree(sgt);
+	return ERR_PTR(-ENOMEM);
 }
 
 /**
- * amdgpu_dma_buf_map_detach - &dma_buf_ops.detach implementation
- * @dma_buf: Shared DMA buffer
+ * amdgpu_dma_buf_unmap - &dma_buf_ops.unmap_dma_buf implementation
  * @attach: DMA-buf attachment
+ * @sgt: sg_table to unmap
+ * @dir: DMA direction
  *
  * This is called when a shared DMA buffer no longer needs to be accessible by
  * another device. For now, simply unpins the buffer from GTT.
  */
-static void amdgpu_dma_buf_map_detach(struct dma_buf *dma_buf,
-				      struct dma_buf_attachment *attach)
+static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
+				 struct sg_table *sgt,
+				 enum dma_data_direction dir)
 {
-	struct drm_gem_object *obj = dma_buf->priv;
+	struct drm_gem_object *obj = attach->dmabuf->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;
 
+	dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
+	sg_free_table(sgt);
+	kfree(sgt);
 	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);
 }
 
 /**
@@ -308,10 +327,11 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf,
 }
 
 const struct dma_buf_ops amdgpu_dmabuf_ops = {
-	.attach = amdgpu_dma_buf_map_attach,
-	.detach = amdgpu_dma_buf_map_detach,
-	.map_dma_buf = drm_gem_map_dma_buf,
-	.unmap_dma_buf = drm_gem_unmap_dma_buf,
+	.dynamic_mapping = true,
+	.attach = amdgpu_dma_buf_attach,
+	.detach = amdgpu_dma_buf_detach,
+	.map_dma_buf = amdgpu_dma_buf_map,
+	.unmap_dma_buf = amdgpu_dma_buf_unmap,
 	.release = drm_gem_dmabuf_release,
 	.begin_cpu_access = amdgpu_dma_buf_begin_cpu_access,
 	.mmap = drm_gem_dmabuf_mmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
index 5012e6ab58f1..ce1b3f017451 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
@@ -25,7 +25,6 @@
 
 #include <drm/drm_gem.h>
 
-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 3fae1007143e..bf5bf15b12e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1409,7 +1409,6 @@ static struct drm_driver kms_driver = {
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_export = amdgpu_gem_prime_export,
 	.gem_prime_import = amdgpu_gem_prime_import,
-	.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 6f0b789a0b49..b319254537b8 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/amdgpu_drm.h>
 #include <drm/drm_cache.h>
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/4] drm/amdgpu: add independent DMA-buf import v8
  2019-10-21 11:15 ` Christian König
@ 2019-10-21 11:15   ` Christian König
  -1 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

Instead of relying on the DRM functions just implement our own import
functions. This prepares 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
v4: split out from unpinned DMA-buf work
v5: rebased and cleanup on new DMA-buf interface
v6: squash with invalidation callback change,
    stop using _(map|unmap)_locked
v7: drop invalidations when the BO is already in system domain
v8: rebase on new DMA-buf patch and drop move notification

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 38 +++++++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h |  4 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c     |  1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c     | 32 ++++++++++++++---
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index f14b52cc7205..c22d11df013e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -370,31 +370,28 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
 }
 
 /**
- * amdgpu_gem_prime_import_sg_table - &drm_driver.gem_prime_import_sg_table
- * implementation
+ * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
+ *
  * @dev: DRM device
- * @attach: DMA-buf attachment
- * @sg: Scatter/gather table
+ * @dma_buf: DMA-buf
  *
- * Imports shared DMA buffer memory exported by another device.
+ * Creates an empty SG BO for DMA-buf import.
  *
  * Returns:
  * A new GEM BO of the given DRM device, representing the memory
  * described by the given DMA-buf attachment and scatter/gather table.
  */
-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_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
 {
-	struct dma_resv *resv = attach->dmabuf->resv;
+	struct dma_resv *resv = dma_buf->resv;
 	struct amdgpu_device *adev = dev->dev_private;
 	struct amdgpu_bo *bo;
 	struct amdgpu_bo_param bp;
 	int ret;
 
 	memset(&bp, 0, sizeof(bp));
-	bp.size = attach->dmabuf->size;
+	bp.size = dma_buf->size;
 	bp.byte_align = PAGE_SIZE;
 	bp.domain = AMDGPU_GEM_DOMAIN_CPU;
 	bp.flags = 0;
@@ -405,11 +402,9 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
 	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;
 
 	dma_resv_unlock(resv);
@@ -434,6 +429,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
 					    struct dma_buf *dma_buf)
 {
+	struct dma_buf_attachment *attach;
 	struct drm_gem_object *obj;
 
 	if (dma_buf->ops == &amdgpu_dmabuf_ops) {
@@ -448,5 +444,17 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
 		}
 	}
 
-	return drm_gem_prime_import(dev, dma_buf);
+	obj = amdgpu_dma_buf_create_obj(dev, dma_buf);
+	if (IS_ERR(obj))
+		return obj;
+
+	attach = dma_buf_dynamic_attach(dma_buf, dev->dev, true);
+	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_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
index ce1b3f017451..ec447a7b6b28 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
@@ -25,10 +25,6 @@
 
 #include <drm/drm_gem.h>
 
-struct drm_gem_object *
-amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
-				 struct dma_buf_attachment *attach,
-				 struct sg_table *sg);
 struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
 					int flags);
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index bf5bf15b12e3..7acca058510c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1409,7 +1409,6 @@ static struct drm_driver kms_driver = {
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_export = amdgpu_gem_prime_export,
 	.gem_prime_import = amdgpu_gem_prime_import,
-	.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,
 	.gem_prime_mmap = amdgpu_gem_prime_mmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 8e867b8b432f..c19100ced040 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -39,6 +39,7 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swiotlb.h>
+#include <linux/dma-buf.h>
 
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
@@ -763,6 +764,7 @@ static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
  */
 struct amdgpu_ttm_tt {
 	struct ttm_dma_tt	ttm;
+	struct drm_gem_object	*gobj;
 	u64			offset;
 	uint64_t		userptr;
 	struct task_struct	*usertask;
@@ -1227,6 +1229,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
 		return NULL;
 	}
 	gtt->ttm.ttm.func = &amdgpu_backend_func;
+	gtt->gobj = &bo->base;
 
 	/* allocate space for the uninitialized page entries */
 	if (ttm_sg_tt_init(&gtt->ttm, bo, page_flags)) {
@@ -1247,7 +1250,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);
 
 	/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
 	if (gtt && gtt->userptr) {
@@ -1260,7 +1262,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->gobj->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);
@@ -1287,9 +1301,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);
@@ -1298,7 +1311,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
 		return;
 	}
 
-	if (slave)
+	if (ttm->sg && gtt->gobj->import_attach) {
+		struct dma_buf_attachment *attach;
+
+		attach = gtt->gobj->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.17.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 4/4] drm/amdgpu: add independent DMA-buf import v8
@ 2019-10-21 11:15   ` Christian König
  0 siblings, 0 replies; 18+ messages in thread
From: Christian König @ 2019-10-21 11:15 UTC (permalink / raw)
  To: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

Instead of relying on the DRM functions just implement our own import
functions. This prepares 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
v4: split out from unpinned DMA-buf work
v5: rebased and cleanup on new DMA-buf interface
v6: squash with invalidation callback change,
    stop using _(map|unmap)_locked
v7: drop invalidations when the BO is already in system domain
v8: rebase on new DMA-buf patch and drop move notification

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 38 +++++++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h |  4 ---
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c     |  1 -
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c     | 32 ++++++++++++++---
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index f14b52cc7205..c22d11df013e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -370,31 +370,28 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
 }
 
 /**
- * amdgpu_gem_prime_import_sg_table - &drm_driver.gem_prime_import_sg_table
- * implementation
+ * amdgpu_dma_buf_create_obj - create BO for DMA-buf import
+ *
  * @dev: DRM device
- * @attach: DMA-buf attachment
- * @sg: Scatter/gather table
+ * @dma_buf: DMA-buf
  *
- * Imports shared DMA buffer memory exported by another device.
+ * Creates an empty SG BO for DMA-buf import.
  *
  * Returns:
  * A new GEM BO of the given DRM device, representing the memory
  * described by the given DMA-buf attachment and scatter/gather table.
  */
-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_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
 {
-	struct dma_resv *resv = attach->dmabuf->resv;
+	struct dma_resv *resv = dma_buf->resv;
 	struct amdgpu_device *adev = dev->dev_private;
 	struct amdgpu_bo *bo;
 	struct amdgpu_bo_param bp;
 	int ret;
 
 	memset(&bp, 0, sizeof(bp));
-	bp.size = attach->dmabuf->size;
+	bp.size = dma_buf->size;
 	bp.byte_align = PAGE_SIZE;
 	bp.domain = AMDGPU_GEM_DOMAIN_CPU;
 	bp.flags = 0;
@@ -405,11 +402,9 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
 	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;
 
 	dma_resv_unlock(resv);
@@ -434,6 +429,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
 					    struct dma_buf *dma_buf)
 {
+	struct dma_buf_attachment *attach;
 	struct drm_gem_object *obj;
 
 	if (dma_buf->ops == &amdgpu_dmabuf_ops) {
@@ -448,5 +444,17 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
 		}
 	}
 
-	return drm_gem_prime_import(dev, dma_buf);
+	obj = amdgpu_dma_buf_create_obj(dev, dma_buf);
+	if (IS_ERR(obj))
+		return obj;
+
+	attach = dma_buf_dynamic_attach(dma_buf, dev->dev, true);
+	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_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
index ce1b3f017451..ec447a7b6b28 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h
@@ -25,10 +25,6 @@
 
 #include <drm/drm_gem.h>
 
-struct drm_gem_object *
-amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
-				 struct dma_buf_attachment *attach,
-				 struct sg_table *sg);
 struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj,
 					int flags);
 struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index bf5bf15b12e3..7acca058510c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -1409,7 +1409,6 @@ static struct drm_driver kms_driver = {
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
 	.gem_prime_export = amdgpu_gem_prime_export,
 	.gem_prime_import = amdgpu_gem_prime_import,
-	.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,
 	.gem_prime_mmap = amdgpu_gem_prime_mmap,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 8e867b8b432f..c19100ced040 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -39,6 +39,7 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swiotlb.h>
+#include <linux/dma-buf.h>
 
 #include <drm/ttm/ttm_bo_api.h>
 #include <drm/ttm/ttm_bo_driver.h>
@@ -763,6 +764,7 @@ static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
  */
 struct amdgpu_ttm_tt {
 	struct ttm_dma_tt	ttm;
+	struct drm_gem_object	*gobj;
 	u64			offset;
 	uint64_t		userptr;
 	struct task_struct	*usertask;
@@ -1227,6 +1229,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo,
 		return NULL;
 	}
 	gtt->ttm.ttm.func = &amdgpu_backend_func;
+	gtt->gobj = &bo->base;
 
 	/* allocate space for the uninitialized page entries */
 	if (ttm_sg_tt_init(&gtt->ttm, bo, page_flags)) {
@@ -1247,7 +1250,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);
 
 	/* user pages are bound by amdgpu_ttm_tt_pin_userptr() */
 	if (gtt && gtt->userptr) {
@@ -1260,7 +1262,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->gobj->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);
@@ -1287,9 +1301,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);
@@ -1298,7 +1311,16 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm)
 		return;
 	}
 
-	if (slave)
+	if (ttm->sg && gtt->gobj->import_attach) {
+		struct dma_buf_attachment *attach;
+
+		attach = gtt->gobj->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.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-21 11:15 ` Christian König
                   ` (3 preceding siblings ...)
  (?)
@ 2019-10-21 21:48 ` Patchwork
  -1 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-10-21 21:48 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/4] dma-buf: change DMA-buf locking convention v2
URL   : https://patchwork.freedesktop.org/series/68330/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
d8e1ae91bced dma-buf: change DMA-buf locking convention v2
-:374: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Christian König <ckoenig.leichtzumerken@gmail.com>'

total: 0 errors, 1 warnings, 0 checks, 316 lines checked
8e66d2945c28 dma-buf: stop using the dmabuf->lock so much
-:82: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Christian König <ckoenig.leichtzumerken@gmail.com>'

total: 0 errors, 1 warnings, 0 checks, 58 lines checked
126819454efd drm/amdgpu: add independent DMA-buf export v7
-:291: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Christian König <ckoenig.leichtzumerken@gmail.com>'

total: 0 errors, 1 warnings, 0 checks, 245 lines checked
24892628be48 drm/amdgpu: add independent DMA-buf import v8
-:220: WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author 'Christian König <ckoenig.leichtzumerken@gmail.com>'

total: 0 errors, 1 warnings, 0 checks, 168 lines checked

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* ✗ Fi.CI.SPARSE: warning for series starting with [1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-21 11:15 ` Christian König
                   ` (4 preceding siblings ...)
  (?)
@ 2019-10-21 21:50 ` Patchwork
  -1 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-10-21 21:50 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/4] dma-buf: change DMA-buf locking convention v2
URL   : https://patchwork.freedesktop.org/series/68330/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Sparse version: v0.6.0
Commit: dma-buf: change DMA-buf locking convention v2
Okay!

Commit: dma-buf: stop using the dmabuf->lock so much
Okay!

Commit: drm/amdgpu: add independent DMA-buf export v7
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:353:16: warning: symbol 'amdgpu_gem_prime_export' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:385:23: warning: symbol 'amdgpu_gem_prime_import_sg_table' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:434:23: warning: symbol 'amdgpu_gem_prime_import' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:51:6: warning: symbol 'amdgpu_gem_prime_vmap' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:71:6: warning: symbol 'amdgpu_gem_prime_vunmap' was not declared. Should it be static?
-drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:89:5: warning: symbol 'amdgpu_gem_prime_mmap' was not declared. Should it be static?
-O:drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:310:26: warning: symbol 'amdgpu_dmabuf_ops' was not declared. Should it be static?
-O:drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c:49:17: warning: symbol 'amdgpu_gem_prime_get_sg_table' was not declared. Should it be static?

Commit: drm/amdgpu: add independent DMA-buf import v8
Okay!

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* ✓ Fi.CI.BAT: success for series starting with [1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-21 11:15 ` Christian König
                   ` (5 preceding siblings ...)
  (?)
@ 2019-10-21 22:13 ` Patchwork
  -1 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-10-21 22:13 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/4] dma-buf: change DMA-buf locking convention v2
URL   : https://patchwork.freedesktop.org/series/68330/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7144 -> Patchwork_14908
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_14908:

### IGT changes ###

#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * {igt@i915_selftest@live_gt_heartbeat}:
    - fi-kbl-8809g:       [PASS][1] -> [DMESG-FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-kbl-8809g/igt@i915_selftest@live_gt_heartbeat.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-kbl-8809g/igt@i915_selftest@live_gt_heartbeat.html
    - fi-skl-6770hq:      [PASS][3] -> [DMESG-FAIL][4]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-skl-6770hq/igt@i915_selftest@live_gt_heartbeat.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-skl-6770hq/igt@i915_selftest@live_gt_heartbeat.html
    - fi-skl-iommu:       [PASS][5] -> [DMESG-FAIL][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-skl-iommu/igt@i915_selftest@live_gt_heartbeat.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-skl-iommu/igt@i915_selftest@live_gt_heartbeat.html

  
Known issues
------------

  Here are the changes found in Patchwork_14908 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@prime_busy@basic-wait-before-default:
    - fi-icl-u3:          [PASS][7] -> [DMESG-WARN][8] ([fdo#107724]) +2 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-icl-u3/igt@prime_busy@basic-wait-before-default.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-icl-u3/igt@prime_busy@basic-wait-before-default.html

  
#### Possible fixes ####

  * igt@gem_mmap@basic:
    - fi-icl-u3:          [DMESG-WARN][9] ([fdo#107724]) -> [PASS][10] +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-icl-u3/igt@gem_mmap@basic.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-icl-u3/igt@gem_mmap@basic.html

  * igt@i915_selftest@live_execlists:
    - fi-icl-u2:          [DMESG-FAIL][11] ([fdo#112046]) -> [PASS][12]
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-icl-u2/igt@i915_selftest@live_execlists.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-icl-u2/igt@i915_selftest@live_execlists.html

  * {igt@i915_selftest@live_gt_heartbeat}:
    - fi-cml-u:           [DMESG-FAIL][13] -> [PASS][14]
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-cml-u/igt@i915_selftest@live_gt_heartbeat.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-cml-u/igt@i915_selftest@live_gt_heartbeat.html

  * igt@i915_selftest@live_hangcheck:
    - {fi-icl-dsi}:       [INCOMPLETE][15] ([fdo#107713] / [fdo#108569]) -> [PASS][16]
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-icl-dsi/igt@i915_selftest@live_hangcheck.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-icl-dsi/igt@i915_selftest@live_hangcheck.html

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       [FAIL][17] ([fdo#111407]) -> [PASS][18]
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/fi-kbl-7500u/igt@kms_chamelium@hdmi-hpd-fast.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#107724]: https://bugs.freedesktop.org/show_bug.cgi?id=107724
  [fdo#108569]: https://bugs.freedesktop.org/show_bug.cgi?id=108569
  [fdo#111407]: https://bugs.freedesktop.org/show_bug.cgi?id=111407
  [fdo#111600]: https://bugs.freedesktop.org/show_bug.cgi?id=111600
  [fdo#111880]: https://bugs.freedesktop.org/show_bug.cgi?id=111880
  [fdo#112046]: https://bugs.freedesktop.org/show_bug.cgi?id=112046


Participating hosts (52 -> 46)
------------------------------

  Additional (1): fi-kbl-soraka 
  Missing    (7): fi-ilk-m540 fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-icl-y fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * Linux: CI_DRM_7144 -> Patchwork_14908

  CI-20190529: 20190529
  CI_DRM_7144: 5a109994e39e3c50909199ed6e970219155b5471 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5235: da9abbab69be80dd00812a4607a4ea2dffcc4544 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_14908: 24892628be4885254faa4878d7f914c61c12b584 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

24892628be48 drm/amdgpu: add independent DMA-buf import v8
126819454efd drm/amdgpu: add independent DMA-buf export v7
8e66d2945c28 dma-buf: stop using the dmabuf->lock so much
d8e1ae91bced dma-buf: change DMA-buf locking convention v2

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/index.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* ✗ Fi.CI.IGT: failure for series starting with [1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-21 11:15 ` Christian König
                   ` (6 preceding siblings ...)
  (?)
@ 2019-10-22  6:46 ` Patchwork
  -1 siblings, 0 replies; 18+ messages in thread
From: Patchwork @ 2019-10-22  6:46 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/4] dma-buf: change DMA-buf locking convention v2
URL   : https://patchwork.freedesktop.org/series/68330/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_7144_full -> Patchwork_14908_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_14908_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_14908_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_14908_full:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@mock_requests:
    - shard-glk:          [PASS][1] -> [DMESG-WARN][2] +1 similar issue
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-glk2/igt@i915_selftest@mock_requests.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-glk4/igt@i915_selftest@mock_requests.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@gem_persistent_relocs@forked-faulting-reloc-thrashing:
    - {shard-tglb}:       NOTRUN -> [INCOMPLETE][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb3/igt@gem_persistent_relocs@forked-faulting-reloc-thrashing.html

  * igt@gem_persistent_relocs@forked-interruptible-thrashing:
    - {shard-tglb}:       NOTRUN -> [FAIL][4]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb6/igt@gem_persistent_relocs@forked-interruptible-thrashing.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-cpu:
    - {shard-tglb}:       [PASS][5] -> [INCOMPLETE][6]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-tglb2/igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-cpu.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb4/igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-shrfb-draw-mmap-cpu.html

  
Known issues
------------

  Here are the changes found in Patchwork_14908_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@bcs0-s3:
    - shard-apl:          [PASS][7] -> [DMESG-WARN][8] ([fdo#108566]) +3 similar issues
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-apl1/igt@gem_ctx_isolation@bcs0-s3.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-apl4/igt@gem_ctx_isolation@bcs0-s3.html

  * igt@gem_ctx_isolation@vcs0-s3:
    - shard-kbl:          [PASS][9] -> [INCOMPLETE][10] ([fdo#103665])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-kbl6/igt@gem_ctx_isolation@vcs0-s3.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-kbl4/igt@gem_ctx_isolation@vcs0-s3.html

  * igt@gem_ctx_shared@q-smoketest-bsd2:
    - shard-iclb:         [PASS][11] -> [SKIP][12] ([fdo#109276]) +11 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb4/igt@gem_ctx_shared@q-smoketest-bsd2.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb8/igt@gem_ctx_shared@q-smoketest-bsd2.html

  * igt@gem_ctx_switch@vcs1-heavy-queue:
    - shard-iclb:         [PASS][13] -> [SKIP][14] ([fdo#112080]) +9 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb2/igt@gem_ctx_switch@vcs1-heavy-queue.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb8/igt@gem_ctx_switch@vcs1-heavy-queue.html

  * igt@gem_exec_schedule@preempt-queue-contexts-chain-bsd:
    - shard-iclb:         [PASS][15] -> [SKIP][16] ([fdo#111325]) +2 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb6/igt@gem_exec_schedule@preempt-queue-contexts-chain-bsd.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@gem_exec_schedule@preempt-queue-contexts-chain-bsd.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy-gup:
    - shard-hsw:          [PASS][17] -> [DMESG-WARN][18] ([fdo#111870])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-hsw1/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy-gup.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-hsw1/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy-gup.html

  * igt@gem_userptr_blits@sync-unmap-cycles:
    - shard-snb:          [PASS][19] -> [DMESG-WARN][20] ([fdo#111870]) +1 similar issue
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-snb7/igt@gem_userptr_blits@sync-unmap-cycles.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-snb6/igt@gem_userptr_blits@sync-unmap-cycles.html

  * igt@i915_pm_rc6_residency@rc6-accuracy:
    - shard-kbl:          [PASS][21] -> [SKIP][22] ([fdo#109271])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-kbl7/igt@i915_pm_rc6_residency@rc6-accuracy.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-kbl2/igt@i915_pm_rc6_residency@rc6-accuracy.html

  * igt@kms_flip@dpms-vs-vblank-race:
    - shard-glk:          [PASS][23] -> [FAIL][24] ([fdo#111609])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-glk8/igt@kms_flip@dpms-vs-vblank-race.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-glk3/igt@kms_flip@dpms-vs-vblank-race.html

  * igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt:
    - shard-iclb:         [PASS][25] -> [FAIL][26] ([fdo#103167]) +3 similar issues
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb5/igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb6/igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-blt.html

  * igt@kms_plane_alpha_blend@pipe-a-coverage-7efc:
    - shard-skl:          [PASS][27] -> [FAIL][28] ([fdo#108145])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-skl5/igt@kms_plane_alpha_blend@pipe-a-coverage-7efc.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-skl7/igt@kms_plane_alpha_blend@pipe-a-coverage-7efc.html

  * igt@kms_plane_lowres@pipe-a-tiling-x:
    - shard-iclb:         [PASS][29] -> [FAIL][30] ([fdo#103166])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb4/igt@kms_plane_lowres@pipe-a-tiling-x.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb8/igt@kms_plane_lowres@pipe-a-tiling-x.html

  * igt@kms_psr@psr2_cursor_mmap_gtt:
    - shard-iclb:         [PASS][31] -> [SKIP][32] ([fdo#109441])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb2/igt@kms_psr@psr2_cursor_mmap_gtt.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb6/igt@kms_psr@psr2_cursor_mmap_gtt.html

  * igt@kms_setmode@basic:
    - shard-apl:          [PASS][33] -> [FAIL][34] ([fdo#99912])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-apl3/igt@kms_setmode@basic.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-apl7/igt@kms_setmode@basic.html

  * igt@kms_vblank@pipe-b-wait-idle-hang:
    - shard-iclb:         [PASS][35] -> [INCOMPLETE][36] ([fdo#107713])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb7/igt@kms_vblank@pipe-b-wait-idle-hang.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb7/igt@kms_vblank@pipe-b-wait-idle-hang.html

  * igt@kms_vblank@pipe-c-query-forked-hang:
    - shard-hsw:          [PASS][37] -> [INCOMPLETE][38] ([fdo#103540])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-hsw1/igt@kms_vblank@pipe-c-query-forked-hang.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-hsw7/igt@kms_vblank@pipe-c-query-forked-hang.html

  * igt@perf_pmu@enable-race-vcs0:
    - shard-apl:          [PASS][39] -> [INCOMPLETE][40] ([fdo#103927]) +1 similar issue
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-apl3/igt@perf_pmu@enable-race-vcs0.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-apl4/igt@perf_pmu@enable-race-vcs0.html

  
#### Possible fixes ####

  * igt@gem_ctx_isolation@vcs1-none:
    - shard-iclb:         [SKIP][41] ([fdo#109276] / [fdo#112080]) -> [PASS][42]
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb8/igt@gem_ctx_isolation@vcs1-none.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@gem_ctx_isolation@vcs1-none.html

  * igt@gem_ctx_switch@vcs1:
    - shard-iclb:         [SKIP][43] ([fdo#112080]) -> [PASS][44] +11 similar issues
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb8/igt@gem_ctx_switch@vcs1.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@gem_ctx_switch@vcs1.html

  * igt@gem_exec_schedule@reorder-wide-bsd:
    - shard-iclb:         [SKIP][45] ([fdo#111325]) -> [PASS][46] +4 similar issues
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb1/igt@gem_exec_schedule@reorder-wide-bsd.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb3/igt@gem_exec_schedule@reorder-wide-bsd.html

  * igt@gem_userptr_blits@dmabuf-unsync:
    - shard-snb:          [DMESG-WARN][47] ([fdo#111870]) -> [PASS][48]
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-snb6/igt@gem_userptr_blits@dmabuf-unsync.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-snb4/igt@gem_userptr_blits@dmabuf-unsync.html

  * igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy:
    - shard-hsw:          [DMESG-WARN][49] ([fdo#111870]) -> [PASS][50] +1 similar issue
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-hsw6/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-hsw5/igt@gem_userptr_blits@map-fixed-invalidate-overlap-busy.html

  * igt@gem_workarounds@suspend-resume-context:
    - {shard-tglb}:       [INCOMPLETE][51] ([fdo#111832] / [fdo#111850]) -> [PASS][52]
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-tglb4/igt@gem_workarounds@suspend-resume-context.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb6/igt@gem_workarounds@suspend-resume-context.html

  * {igt@i915_pm_dc@dc6-dpms}:
    - shard-iclb:         [FAIL][53] ([fdo#110548]) -> [PASS][54]
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb4/igt@i915_pm_dc@dc6-dpms.html
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb8/igt@i915_pm_dc@dc6-dpms.html

  * igt@i915_pm_rpm@modeset-stress-extra-wait:
    - shard-glk:          [DMESG-WARN][55] ([fdo#105763] / [fdo#106538]) -> [PASS][56]
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-glk8/igt@i915_pm_rpm@modeset-stress-extra-wait.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-glk2/igt@i915_pm_rpm@modeset-stress-extra-wait.html

  * igt@i915_suspend@sysfs-reader:
    - shard-apl:          [DMESG-WARN][57] ([fdo#108566]) -> [PASS][58] +5 similar issues
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-apl6/igt@i915_suspend@sysfs-reader.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-apl4/igt@i915_suspend@sysfs-reader.html

  * igt@kms_cursor_crc@pipe-b-cursor-64x21-sliding:
    - shard-iclb:         [INCOMPLETE][59] ([fdo#107713]) -> [PASS][60]
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb1/igt@kms_cursor_crc@pipe-b-cursor-64x21-sliding.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@kms_cursor_crc@pipe-b-cursor-64x21-sliding.html

  * igt@kms_draw_crc@draw-method-xrgb8888-mmap-cpu-xtiled:
    - shard-snb:          [SKIP][61] ([fdo#109271]) -> [PASS][62] +2 similar issues
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-snb2/igt@kms_draw_crc@draw-method-xrgb8888-mmap-cpu-xtiled.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-snb6/igt@kms_draw_crc@draw-method-xrgb8888-mmap-cpu-xtiled.html

  * igt@kms_frontbuffer_tracking@fbc-1p-pri-indfb-multidraw:
    - shard-iclb:         [FAIL][63] ([fdo#103167]) -> [PASS][64] +4 similar issues
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb8/igt@kms_frontbuffer_tracking@fbc-1p-pri-indfb-multidraw.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@kms_frontbuffer_tracking@fbc-1p-pri-indfb-multidraw.html

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move:
    - {shard-tglb}:       [FAIL][65] ([fdo#103167]) -> [PASS][66] +2 similar issues
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-tglb8/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move.html
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb2/igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-move.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min:
    - shard-skl:          [FAIL][67] ([fdo#108145]) -> [PASS][68] +1 similar issue
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-skl6/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-skl5/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html

  * igt@kms_plane_alpha_blend@pipe-c-coverage-7efc:
    - shard-skl:          [FAIL][69] ([fdo#108145] / [fdo#110403]) -> [PASS][70] +1 similar issue
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-skl2/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-skl4/igt@kms_plane_alpha_blend@pipe-c-coverage-7efc.html

  * igt@kms_psr@psr2_primary_page_flip:
    - shard-iclb:         [SKIP][71] ([fdo#109441]) -> [PASS][72]
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb6/igt@kms_psr@psr2_primary_page_flip.html
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb2/igt@kms_psr@psr2_primary_page_flip.html

  * igt@kms_vblank@pipe-d-ts-continuation-suspend:
    - {shard-tglb}:       [INCOMPLETE][73] ([fdo#111850]) -> [PASS][74]
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-tglb1/igt@kms_vblank@pipe-d-ts-continuation-suspend.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-tglb3/igt@kms_vblank@pipe-d-ts-continuation-suspend.html

  * igt@prime_busy@hang-bsd2:
    - shard-iclb:         [SKIP][75] ([fdo#109276]) -> [PASS][76] +18 similar issues
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb5/igt@prime_busy@hang-bsd2.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb4/igt@prime_busy@hang-bsd2.html

  
#### Warnings ####

  * igt@gem_ctx_isolation@vcs1-nonpriv:
    - shard-iclb:         [SKIP][77] ([fdo#109276] / [fdo#112080]) -> [FAIL][78] ([fdo#111329])
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb8/igt@gem_ctx_isolation@vcs1-nonpriv.html
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb1/igt@gem_ctx_isolation@vcs1-nonpriv.html

  * igt@gem_mocs_settings@mocs-reset-bsd2:
    - shard-iclb:         [SKIP][79] ([fdo#109276]) -> [FAIL][80] ([fdo#111330]) +1 similar issue
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb6/igt@gem_mocs_settings@mocs-reset-bsd2.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb2/igt@gem_mocs_settings@mocs-reset-bsd2.html

  * igt@gem_mocs_settings@mocs-settings-bsd2:
    - shard-iclb:         [FAIL][81] ([fdo#111330]) -> [SKIP][82] ([fdo#109276])
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7144/shard-iclb4/igt@gem_mocs_settings@mocs-settings-bsd2.html
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/shard-iclb8/igt@gem_mocs_settings@mocs-settings-bsd2.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo# 111852 ]: https://bugs.freedesktop.org/show_bug.cgi?id= 111852 
  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#103665]: https://bugs.freedesktop.org/show_bug.cgi?id=103665
  [fdo#103927]: https://bugs.freedesktop.org/show_bug.cgi?id=103927
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#106538]: https://bugs.freedesktop.org/show_bug.cgi?id=106538
  [fdo#107713]: https://bugs.freedesktop.org/show_bug.cgi?id=107713
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#108566]: https://bugs.freedesktop.org/show_bug.cgi?id=108566
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109276]: https://bugs.freedesktop.org/show_bug.cgi?id=109276
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#110403]: https://bugs.freedesktop.org/show_bug.cgi?id=110403
  [fdo#110548]: https://bugs.freedesktop.org/show_bug.cgi?id=110548
  [fdo#111325]: https://bugs.freedesktop.org/show_bug.cgi?id=111325
  [fdo#111329]: https://bugs.freedesktop.org/show_bug.cgi?id=111329
  [fdo#111330]: https://bugs.freedesktop.org/show_bug.cgi?id=111330
  [fdo#111609]: https://bugs.freedesktop.org/show_bug.cgi?id=111609
  [fdo#111703]: https://bugs.freedesktop.org/show_bug.cgi?id=111703
  [fdo#111832]: https://bugs.freedesktop.org/show_bug.cgi?id=111832
  [fdo#111850]: https://bugs.freedesktop.org/show_bug.cgi?id=111850
  [fdo#111870]: https://bugs.freedesktop.org/show_bug.cgi?id=111870
  [fdo#111884]: https://bugs.freedesktop.org/show_bug.cgi?id=111884
  [fdo#112080]: https://bugs.freedesktop.org/show_bug.cgi?id=112080
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (11 -> 11)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * CI: CI-20190529 -> None
  * Linux: CI_DRM_7144 -> Patchwork_14908

  CI-20190529: 20190529
  CI_DRM_7144: 5a109994e39e3c50909199ed6e970219155b5471 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5235: da9abbab69be80dd00812a4607a4ea2dffcc4544 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_14908: 24892628be4885254faa4878d7f914c61c12b584 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_14908/index.html
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-21 11:15 ` Christian König
@ 2019-10-22 10:01   ` Daniel Vetter
  -1 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:01 UTC (permalink / raw)
  To: Christian König
  Cc: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

On Mon, Oct 21, 2019 at 01:15:21PM +0200, Christian König wrote:
> This patch is a stripped down version of the locking changes
> necessary to support dynamic DMA-buf handling.
> 
> It adds a dynamic flag for both importers as well as exporters
> so that drivers can choose if they want the reservation object
> locked or unlocked during mapping of attachments.
> 
> For compatibility between drivers we cache the DMA-buf mapping
> during attaching an importer as soon as exporter/importer
> disagree on the dynamic handling.
> 
> This change has gone through a lengthy discussion on dri-devel
> and other mailing lists with at least 3-4 different attempts and
> dead-ends until we settled on this solution. Please refer to the
> mailing lists archives for full background on the history of
> this change.

I kinda hoped for a real write-up of why we ended up here, not a "please
read the last year or so of dri-devel" ...

So here's what I think we need to minimally mention, pls add:

<cut>
Issues and solutions we considered:

- We can't change all existing drivers, and existing drivers have strong
  opinions about which locks they're holding while calling
  dma_buf_attachment_map/unmap. The solution to avoid this was to move the
  actual map/unmap out from this call, into the attach/detach callbacks,
  and cache the mapping. This works because drivers don't call
  attach/detach from deep within their code callchains (like deep in
  memory management code called from cs/execbuf ioctl), but directly from
  the fd2handle implementation.

- The caching has some troubles on some soc drivers, which set other modes
  than DMA_BIDIRECTIONAL. We can't have 2 incompatible mappings, and we
  can't re-create the mapping at _map time due to the above locking fun.
  We very carefuly step around that by only caching at attach time if the
  dynamic mode between importer/expoert mismatches.

- There's been quite some discussion on dma-buf mappings which need active
  cache management, which would all break down when caching, plus we don't
  have explicit flush operations on the attachment side. The solution to
  this was to shrug and keep the current discrepancy between what the
  dma-buf docs claim and what implementations do, with the hope that the
  begin/end_cpu_access hooks are good enough and that all necessary
  flushing to keep device mappings consistent will be done there.
</cut>
> 
> v2: cleanup set_name merge, improve kerneldoc
> 
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
>  include/linux/dma-buf.h   |  57 +++++++++++++++++++--
>  2 files changed, 143 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 433d91d710e4..753be84b5fd6 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
>  	size_t ret = 0;
>  
>  	dmabuf = dentry->d_fsdata;
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (dmabuf->name)
>  		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  
>  	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
>  			     dentry->d_name.name, ret > 0 ? name : "");
> @@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
>  	if (IS_ERR(name))
>  		return PTR_ERR(name);
>  
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (!list_empty(&dmabuf->attachments)) {
>  		ret = -EBUSY;
>  		kfree(name);
> @@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
>  	dmabuf->name = name;
>  
>  out_unlock:
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  	return ret;
>  }
>  
> @@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
>  	/* Don't count the temporary reference taken inside procfs seq_show */
>  	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
>  	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (dmabuf->name)
>  		seq_printf(m, "name:\t%s\n", dmabuf->name);
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  }
>  
>  static const struct file_operations dma_buf_fops = {
> @@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
>  		return ERR_PTR(-EINVAL);
>  	}
>  
> +	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
> +		    exp_info->ops->dynamic_mapping))
> +		return ERR_PTR(-EINVAL);
> +
>  	if (!try_module_get(exp_info->owner))
>  		return ERR_PTR(-ENOENT);
>  
> @@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
>  EXPORT_SYMBOL_GPL(dma_buf_put);
>  
>  /**
> - * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
> + * dma_buf_dynamic_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.
> + * @dmabuf:		[in]	buffer to attach device to.
> + * @dev:		[in]	device to be attached.
> + * @dynamic_mapping:	[in]	calling convention for map/unmap
>   *
>   * Returns struct dma_buf_attachment pointer for this attachment. Attachments
>   * must be cleaned up by calling dma_buf_detach().
> @@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> +		       bool dynamic_mapping)
>  {
>  	struct dma_buf_attachment *attach;
>  	int ret;
> @@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
>  
>  	attach->dev = dev;
>  	attach->dmabuf = dmabuf;
> +	attach->dynamic_mapping = dynamic_mapping;
>  
>  	mutex_lock(&dmabuf->lock);
>  
> @@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
>  		if (ret)
>  			goto err_attach;
>  	}
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	list_add(&attach->node, &dmabuf->attachments);
> +	dma_resv_unlock(dmabuf->resv);
>  
>  	mutex_unlock(&dmabuf->lock);
>  
> +	/* When either the importer or the exporter can't handle dynamic
> +	 * mappings we cache the mapping here to avoid issues with the
> +	 * reservation object lock.
> +	 */
> +	if (dma_buf_attachment_is_dynamic(attach) !=
> +	    dma_buf_is_dynamic(dmabuf)) {
> +		struct sg_table *sgt;
> +
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_lock(attach->dmabuf->resv, NULL);
> +
> +		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
> +		if (!sgt)
> +			sgt = ERR_PTR(-ENOMEM);
> +		if (IS_ERR(sgt)) {
> +			ret = PTR_ERR(sgt);
> +			goto err_unlock;
> +		}
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_unlock(attach->dmabuf->resv);
> +		attach->sgt = sgt;
> +		attach->dir = DMA_BIDIRECTIONAL;
> +	}
> +
>  	return attach;
>  
>  err_attach:
>  	kfree(attach);
>  	mutex_unlock(&dmabuf->lock);
>  	return ERR_PTR(ret);
> +
> +err_unlock:
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_unlock(attach->dmabuf->resv);
> +
> +	dma_buf_detach(dmabuf, attach);
> +	return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
> +
> +/**
> + * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
> + * @dmabuf:	[in]	buffer to attach device to.
> + * @dev:	[in]	device to be attached.
> + *
> + * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
> + * mapping.
> + */
> +struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> +					  struct device *dev)
> +{
> +	return dma_buf_dynamic_attach(dmabuf, dev, false);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_attach);
>  
> @@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
>  	if (WARN_ON(!dmabuf || !attach))
>  		return;
>  
> -	if (attach->sgt)
> +	if (attach->sgt) {
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_lock(attach->dmabuf->resv, NULL);
> +
>  		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
>  
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_unlock(attach->dmabuf->resv);
> +	}
> +
>  	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	list_del(&attach->node);
> +	dma_resv_unlock(dmabuf->resv);
>  	if (dmabuf->ops->detach)
>  		dmabuf->ops->detach(dmabuf, attach);
>  
> @@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>  	if (WARN_ON(!attach || !attach->dmabuf))
>  		return ERR_PTR(-EINVAL);
>  
> +	if (dma_buf_attachment_is_dynamic(attach))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	if (attach->sgt) {
>  		/*
>  		 * Two mappings with different directions for the same
> @@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>  		return attach->sgt;
>  	}
>  
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_assert_held(attach->dmabuf->resv);

Almost tripped me up until I noticed your check for the buf/exporter here.
Nice check!

Maybe we could do an

	else
		lockdep_assert_not_held()

here? Open-coded ofc (or put it into drm_utils.h, I don't want to hold up
this patch any longer, then move it to lockdep.h later on), since
currently doesn't exist. Just to _really_ enforce the documented contract
here.

> +
>  	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
>  	if (!sg_table)
>  		sg_table = ERR_PTR(-ENOMEM);
> @@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
>  	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
>  		return;
>  
> +	if (dma_buf_attachment_is_dynamic(attach))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	if (attach->sgt == sg_table)
>  		return;
>  
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
> @@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  		seq_puts(s, "\tAttached Devices:\n");
>  		attach_count = 0;
>  
> +		dma_resv_lock(buf_obj->resv, NULL);

You've switched dmabuf->name to be protected by dma_resv too, so this
needs to be moved up above the seq_printf which prints ->name.

>  		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
>  			seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
>  			attach_count++;
>  		}
> +		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -42,6 +42,18 @@ struct dma_buf_ops {
>  	  */
>  	bool cache_sgt_mapping;
>  
> +	/**
> +	 * @dynamic_mapping:
> +	 *
> +	 * If true the framework makes sure that the map/unmap_dma_buf
> +	 * callbacks are always called with the dma_resv object locked.
> +	 *
> +	 * If false the framework makes ure that the map/unmap_dma_buf

s/ure/sure/

> +	 * callbacks are always called without the dma_resv object locked.
> +	 * Mutual exclusive with @cache_sgt_mapping.
> +	 */
> +	bool dynamic_mapping;
> +
>  	/**
>  	 * @attach:
>  	 *
> @@ -109,6 +121,9 @@ struct dma_buf_ops {
>  	 * any other kind of sharing that the exporter might wish to make
>  	 * available to buffer-users.
>  	 *
> +	 * This is always called with the dmabuf->resv object locked when
> +	 * the dynamic_mapping flag is true.
> +	 *
>  	 * Returns:
>  	 *
>  	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
> @@ -267,7 +282,8 @@ struct dma_buf_ops {
>   * struct dma_buf - shared buffer object
>   * @size: size of the buffer
>   * @file: file pointer used for sharing buffers across, and for refcounting.
> - * @attachments: list of dma_buf_attachment that denotes all devices attached.
> + * @attachments: list of dma_buf_attachment that denotes all devices attached,
> + *               protected by dma_resv lock.
>   * @ops: dma_buf_ops associated with this buffer object.
>   * @lock: used internally to serialize list manipulation, attach/detach and
>   *        vmap/unmap, and accesses to name

@name in dma_buf needs to be updated to mention that it's protected by
dma_resv lock.

> @@ -323,10 +339,12 @@ struct dma_buf {
>   * struct dma_buf_attachment - holds device-buffer attachment data
>   * @dmabuf: buffer for this attachment.
>   * @dev: device attached to the buffer.
> - * @node: list of dma_buf_attachment.
> + * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
>   * @sgt: cached mapping.
>   * @dir: direction of cached mapping.
>   * @priv: exporter specific attachment data.
> + * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
> + * dma_resv lock held.
>   *
>   * This structure holds the attachment information between the dma_buf buffer
>   * and its user device(s). The list contains one attachment struct per device
> @@ -343,6 +361,7 @@ struct dma_buf_attachment {
>  	struct list_head node;
>  	struct sg_table *sgt;
>  	enum dma_data_direction dir;
> +	bool dynamic_mapping;
>  	void *priv;
>  };
>  
> @@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
>  	get_file(dmabuf->file);
>  }
>  
> +/**
> + * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
> + * @dmabuf: the DMA-buf to check
> + *
> + * Returns true if a DMA-buf exporter wants to be called with the dma_resv
> + * locked, false if it doesn't wants to be called with the lock held.

Maybe added "... for the map/unmap callbacks, ..." since we don't
guarantee to hold the lock for all callbacks. You clarify this already
below.

> + */
> +static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
> +{
> +	return dmabuf->ops->dynamic_mapping;
> +}
> +
> +/**
> + * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
> + * mappinsg
> + * @attach: the DMA-buf attachment to check
> + *
> + * Returns true if a DMA-buf importer wants to call the map/unmap functions with
> + * the dma_resv lock held.
> + */
> +static inline bool
> +dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
> +{
> +	return attach->dynamic_mapping;
> +}
> +
>  struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> -							struct device *dev);
> +					  struct device *dev);
> +struct dma_buf_attachment *
> +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> +		       bool dynamic_mapping);
>  void dma_buf_detach(struct dma_buf *dmabuf,
> -				struct dma_buf_attachment *dmabuf_attach);
> +		    struct dma_buf_attachment *attach);
>  
>  struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
>  
> @@ -409,6 +457,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_move_notify(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,

With the nits all addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> -- 
> 2.17.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
@ 2019-10-22 10:01   ` Daniel Vetter
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:01 UTC (permalink / raw)
  To: Christian König
  Cc: intel-gfx, dri-devel, linaro-mm-sig, sumit.semwal, linux-media

On Mon, Oct 21, 2019 at 01:15:21PM +0200, Christian König wrote:
> This patch is a stripped down version of the locking changes
> necessary to support dynamic DMA-buf handling.
> 
> It adds a dynamic flag for both importers as well as exporters
> so that drivers can choose if they want the reservation object
> locked or unlocked during mapping of attachments.
> 
> For compatibility between drivers we cache the DMA-buf mapping
> during attaching an importer as soon as exporter/importer
> disagree on the dynamic handling.
> 
> This change has gone through a lengthy discussion on dri-devel
> and other mailing lists with at least 3-4 different attempts and
> dead-ends until we settled on this solution. Please refer to the
> mailing lists archives for full background on the history of
> this change.

I kinda hoped for a real write-up of why we ended up here, not a "please
read the last year or so of dri-devel" ...

So here's what I think we need to minimally mention, pls add:

<cut>
Issues and solutions we considered:

- We can't change all existing drivers, and existing drivers have strong
  opinions about which locks they're holding while calling
  dma_buf_attachment_map/unmap. The solution to avoid this was to move the
  actual map/unmap out from this call, into the attach/detach callbacks,
  and cache the mapping. This works because drivers don't call
  attach/detach from deep within their code callchains (like deep in
  memory management code called from cs/execbuf ioctl), but directly from
  the fd2handle implementation.

- The caching has some troubles on some soc drivers, which set other modes
  than DMA_BIDIRECTIONAL. We can't have 2 incompatible mappings, and we
  can't re-create the mapping at _map time due to the above locking fun.
  We very carefuly step around that by only caching at attach time if the
  dynamic mode between importer/expoert mismatches.

- There's been quite some discussion on dma-buf mappings which need active
  cache management, which would all break down when caching, plus we don't
  have explicit flush operations on the attachment side. The solution to
  this was to shrug and keep the current discrepancy between what the
  dma-buf docs claim and what implementations do, with the hope that the
  begin/end_cpu_access hooks are good enough and that all necessary
  flushing to keep device mappings consistent will be done there.
</cut>
> 
> v2: cleanup set_name merge, improve kerneldoc
> 
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
>  include/linux/dma-buf.h   |  57 +++++++++++++++++++--
>  2 files changed, 143 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 433d91d710e4..753be84b5fd6 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
>  	size_t ret = 0;
>  
>  	dmabuf = dentry->d_fsdata;
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (dmabuf->name)
>  		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  
>  	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
>  			     dentry->d_name.name, ret > 0 ? name : "");
> @@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
>  	if (IS_ERR(name))
>  		return PTR_ERR(name);
>  
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (!list_empty(&dmabuf->attachments)) {
>  		ret = -EBUSY;
>  		kfree(name);
> @@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
>  	dmabuf->name = name;
>  
>  out_unlock:
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  	return ret;
>  }
>  
> @@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
>  	/* Don't count the temporary reference taken inside procfs seq_show */
>  	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
>  	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
> -	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	if (dmabuf->name)
>  		seq_printf(m, "name:\t%s\n", dmabuf->name);
> -	mutex_unlock(&dmabuf->lock);
> +	dma_resv_unlock(dmabuf->resv);
>  }
>  
>  static const struct file_operations dma_buf_fops = {
> @@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
>  		return ERR_PTR(-EINVAL);
>  	}
>  
> +	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
> +		    exp_info->ops->dynamic_mapping))
> +		return ERR_PTR(-EINVAL);
> +
>  	if (!try_module_get(exp_info->owner))
>  		return ERR_PTR(-ENOENT);
>  
> @@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
>  EXPORT_SYMBOL_GPL(dma_buf_put);
>  
>  /**
> - * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
> + * dma_buf_dynamic_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.
> + * @dmabuf:		[in]	buffer to attach device to.
> + * @dev:		[in]	device to be attached.
> + * @dynamic_mapping:	[in]	calling convention for map/unmap
>   *
>   * Returns struct dma_buf_attachment pointer for this attachment. Attachments
>   * must be cleaned up by calling dma_buf_detach().
> @@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> +		       bool dynamic_mapping)
>  {
>  	struct dma_buf_attachment *attach;
>  	int ret;
> @@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
>  
>  	attach->dev = dev;
>  	attach->dmabuf = dmabuf;
> +	attach->dynamic_mapping = dynamic_mapping;
>  
>  	mutex_lock(&dmabuf->lock);
>  
> @@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
>  		if (ret)
>  			goto err_attach;
>  	}
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	list_add(&attach->node, &dmabuf->attachments);
> +	dma_resv_unlock(dmabuf->resv);
>  
>  	mutex_unlock(&dmabuf->lock);
>  
> +	/* When either the importer or the exporter can't handle dynamic
> +	 * mappings we cache the mapping here to avoid issues with the
> +	 * reservation object lock.
> +	 */
> +	if (dma_buf_attachment_is_dynamic(attach) !=
> +	    dma_buf_is_dynamic(dmabuf)) {
> +		struct sg_table *sgt;
> +
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_lock(attach->dmabuf->resv, NULL);
> +
> +		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
> +		if (!sgt)
> +			sgt = ERR_PTR(-ENOMEM);
> +		if (IS_ERR(sgt)) {
> +			ret = PTR_ERR(sgt);
> +			goto err_unlock;
> +		}
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_unlock(attach->dmabuf->resv);
> +		attach->sgt = sgt;
> +		attach->dir = DMA_BIDIRECTIONAL;
> +	}
> +
>  	return attach;
>  
>  err_attach:
>  	kfree(attach);
>  	mutex_unlock(&dmabuf->lock);
>  	return ERR_PTR(ret);
> +
> +err_unlock:
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_unlock(attach->dmabuf->resv);
> +
> +	dma_buf_detach(dmabuf, attach);
> +	return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
> +
> +/**
> + * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
> + * @dmabuf:	[in]	buffer to attach device to.
> + * @dev:	[in]	device to be attached.
> + *
> + * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
> + * mapping.
> + */
> +struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> +					  struct device *dev)
> +{
> +	return dma_buf_dynamic_attach(dmabuf, dev, false);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_attach);
>  
> @@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
>  	if (WARN_ON(!dmabuf || !attach))
>  		return;
>  
> -	if (attach->sgt)
> +	if (attach->sgt) {
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_lock(attach->dmabuf->resv, NULL);
> +
>  		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
>  
> +		if (dma_buf_is_dynamic(attach->dmabuf))
> +			dma_resv_unlock(attach->dmabuf->resv);
> +	}
> +
>  	mutex_lock(&dmabuf->lock);
> +	dma_resv_lock(dmabuf->resv, NULL);
>  	list_del(&attach->node);
> +	dma_resv_unlock(dmabuf->resv);
>  	if (dmabuf->ops->detach)
>  		dmabuf->ops->detach(dmabuf, attach);
>  
> @@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>  	if (WARN_ON(!attach || !attach->dmabuf))
>  		return ERR_PTR(-EINVAL);
>  
> +	if (dma_buf_attachment_is_dynamic(attach))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	if (attach->sgt) {
>  		/*
>  		 * Two mappings with different directions for the same
> @@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>  		return attach->sgt;
>  	}
>  
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_assert_held(attach->dmabuf->resv);

Almost tripped me up until I noticed your check for the buf/exporter here.
Nice check!

Maybe we could do an

	else
		lockdep_assert_not_held()

here? Open-coded ofc (or put it into drm_utils.h, I don't want to hold up
this patch any longer, then move it to lockdep.h later on), since
currently doesn't exist. Just to _really_ enforce the documented contract
here.

> +
>  	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
>  	if (!sg_table)
>  		sg_table = ERR_PTR(-ENOMEM);
> @@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
>  	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
>  		return;
>  
> +	if (dma_buf_attachment_is_dynamic(attach))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	if (attach->sgt == sg_table)
>  		return;
>  
> +	if (dma_buf_is_dynamic(attach->dmabuf))
> +		dma_resv_assert_held(attach->dmabuf->resv);
> +
>  	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
> @@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  		seq_puts(s, "\tAttached Devices:\n");
>  		attach_count = 0;
>  
> +		dma_resv_lock(buf_obj->resv, NULL);

You've switched dmabuf->name to be protected by dma_resv too, so this
needs to be moved up above the seq_printf which prints ->name.

>  		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
>  			seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
>  			attach_count++;
>  		}
> +		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -42,6 +42,18 @@ struct dma_buf_ops {
>  	  */
>  	bool cache_sgt_mapping;
>  
> +	/**
> +	 * @dynamic_mapping:
> +	 *
> +	 * If true the framework makes sure that the map/unmap_dma_buf
> +	 * callbacks are always called with the dma_resv object locked.
> +	 *
> +	 * If false the framework makes ure that the map/unmap_dma_buf

s/ure/sure/

> +	 * callbacks are always called without the dma_resv object locked.
> +	 * Mutual exclusive with @cache_sgt_mapping.
> +	 */
> +	bool dynamic_mapping;
> +
>  	/**
>  	 * @attach:
>  	 *
> @@ -109,6 +121,9 @@ struct dma_buf_ops {
>  	 * any other kind of sharing that the exporter might wish to make
>  	 * available to buffer-users.
>  	 *
> +	 * This is always called with the dmabuf->resv object locked when
> +	 * the dynamic_mapping flag is true.
> +	 *
>  	 * Returns:
>  	 *
>  	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
> @@ -267,7 +282,8 @@ struct dma_buf_ops {
>   * struct dma_buf - shared buffer object
>   * @size: size of the buffer
>   * @file: file pointer used for sharing buffers across, and for refcounting.
> - * @attachments: list of dma_buf_attachment that denotes all devices attached.
> + * @attachments: list of dma_buf_attachment that denotes all devices attached,
> + *               protected by dma_resv lock.
>   * @ops: dma_buf_ops associated with this buffer object.
>   * @lock: used internally to serialize list manipulation, attach/detach and
>   *        vmap/unmap, and accesses to name

@name in dma_buf needs to be updated to mention that it's protected by
dma_resv lock.

> @@ -323,10 +339,12 @@ struct dma_buf {
>   * struct dma_buf_attachment - holds device-buffer attachment data
>   * @dmabuf: buffer for this attachment.
>   * @dev: device attached to the buffer.
> - * @node: list of dma_buf_attachment.
> + * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
>   * @sgt: cached mapping.
>   * @dir: direction of cached mapping.
>   * @priv: exporter specific attachment data.
> + * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
> + * dma_resv lock held.
>   *
>   * This structure holds the attachment information between the dma_buf buffer
>   * and its user device(s). The list contains one attachment struct per device
> @@ -343,6 +361,7 @@ struct dma_buf_attachment {
>  	struct list_head node;
>  	struct sg_table *sgt;
>  	enum dma_data_direction dir;
> +	bool dynamic_mapping;
>  	void *priv;
>  };
>  
> @@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
>  	get_file(dmabuf->file);
>  }
>  
> +/**
> + * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
> + * @dmabuf: the DMA-buf to check
> + *
> + * Returns true if a DMA-buf exporter wants to be called with the dma_resv
> + * locked, false if it doesn't wants to be called with the lock held.

Maybe added "... for the map/unmap callbacks, ..." since we don't
guarantee to hold the lock for all callbacks. You clarify this already
below.

> + */
> +static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
> +{
> +	return dmabuf->ops->dynamic_mapping;
> +}
> +
> +/**
> + * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
> + * mappinsg
> + * @attach: the DMA-buf attachment to check
> + *
> + * Returns true if a DMA-buf importer wants to call the map/unmap functions with
> + * the dma_resv lock held.
> + */
> +static inline bool
> +dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
> +{
> +	return attach->dynamic_mapping;
> +}
> +
>  struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> -							struct device *dev);
> +					  struct device *dev);
> +struct dma_buf_attachment *
> +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> +		       bool dynamic_mapping);
>  void dma_buf_detach(struct dma_buf *dmabuf,
> -				struct dma_buf_attachment *dmabuf_attach);
> +		    struct dma_buf_attachment *attach);
>  
>  struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
>  
> @@ -409,6 +457,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_move_notify(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,

With the nits all addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> -- 
> 2.17.1
> 

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
  2019-10-22 10:01   ` Daniel Vetter
@ 2019-10-22 10:04     ` Daniel Vetter
  -1 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:04 UTC (permalink / raw)
  To: Christian König
  Cc: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

On Tue, Oct 22, 2019 at 12:01:30PM +0200, Daniel Vetter wrote:
> On Mon, Oct 21, 2019 at 01:15:21PM +0200, Christian König wrote:
> > This patch is a stripped down version of the locking changes
> > necessary to support dynamic DMA-buf handling.
> > 
> > It adds a dynamic flag for both importers as well as exporters
> > so that drivers can choose if they want the reservation object
> > locked or unlocked during mapping of attachments.
> > 
> > For compatibility between drivers we cache the DMA-buf mapping
> > during attaching an importer as soon as exporter/importer
> > disagree on the dynamic handling.
> > 
> > This change has gone through a lengthy discussion on dri-devel
> > and other mailing lists with at least 3-4 different attempts and
> > dead-ends until we settled on this solution. Please refer to the
> > mailing lists archives for full background on the history of
> > this change.

Two more refinments below, I hit send a notch too early.
> 
> I kinda hoped for a real write-up of why we ended up here, not a "please
> read the last year or so of dri-devel" ...
> 
> So here's what I think we need to minimally mention, pls add:
> 
> <cut>
> Issues and solutions we considered:
> 
> - We can't change all existing drivers, and existing drivers have strong
>   opinions about which locks they're holding while calling
>   dma_buf_attachment_map/unmap. The solution to avoid this was to move the

Maybe add here "Exporters also have strong opinions about which locks they
can acquire in their ->map/unmap callbacks, levaing no room for change."

>   actual map/unmap out from this call, into the attach/detach callbacks,
>   and cache the mapping. This works because drivers don't call
>   attach/detach from deep within their code callchains (like deep in
>   memory management code called from cs/execbuf ioctl), but directly from
>   the fd2handle implementation.
> 
> - The caching has some troubles on some soc drivers, which set other modes
>   than DMA_BIDIRECTIONAL. We can't have 2 incompatible mappings, and we
>   can't re-create the mapping at _map time due to the above locking fun.
>   We very carefuly step around that by only caching at attach time if the
>   dynamic mode between importer/expoert mismatches.
> 
> - There's been quite some discussion on dma-buf mappings which need active
>   cache management, which would all break down when caching, plus we don't
>   have explicit flush operations on the attachment side. The solution to
>   this was to shrug and keep the current discrepancy between what the
>   dma-buf docs claim and what implementations do, with the hope that the
>   begin/end_cpu_access hooks are good enough and that all necessary
>   flushing to keep device mappings consistent will be done there.
> </cut>
> > 
> > v2: cleanup set_name merge, improve kerneldoc
> > 
> > Signed-off-by: Christian König <christian.koenig@amd.com>
> > ---
> >  drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
> >  include/linux/dma-buf.h   |  57 +++++++++++++++++++--
> >  2 files changed, 143 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index 433d91d710e4..753be84b5fd6 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
> >  	size_t ret = 0;
> >  
> >  	dmabuf = dentry->d_fsdata;
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (dmabuf->name)
> >  		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  
> >  	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
> >  			     dentry->d_name.name, ret > 0 ? name : "");
> > @@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
> >  	if (IS_ERR(name))
> >  		return PTR_ERR(name);
> >  
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (!list_empty(&dmabuf->attachments)) {
> >  		ret = -EBUSY;
> >  		kfree(name);
> > @@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
> >  	dmabuf->name = name;
> >  
> >  out_unlock:
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  	return ret;
> >  }
> >  
> > @@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
> >  	/* Don't count the temporary reference taken inside procfs seq_show */
> >  	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
> >  	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (dmabuf->name)
> >  		seq_printf(m, "name:\t%s\n", dmabuf->name);
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  }
> >  
> >  static const struct file_operations dma_buf_fops = {
> > @@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> >  		return ERR_PTR(-EINVAL);
> >  	}
> >  
> > +	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
> > +		    exp_info->ops->dynamic_mapping))
> > +		return ERR_PTR(-EINVAL);
> > +
> >  	if (!try_module_get(exp_info->owner))
> >  		return ERR_PTR(-ENOENT);
> >  
> > @@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
> >  EXPORT_SYMBOL_GPL(dma_buf_put);
> >  
> >  /**
> > - * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
> > + * dma_buf_dynamic_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.
> > + * @dmabuf:		[in]	buffer to attach device to.
> > + * @dev:		[in]	device to be attached.
> > + * @dynamic_mapping:	[in]	calling convention for map/unmap
> >   *
> >   * Returns struct dma_buf_attachment pointer for this attachment. Attachments
> >   * must be cleaned up by calling dma_buf_detach().
> > @@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> > +		       bool dynamic_mapping)
> >  {
> >  	struct dma_buf_attachment *attach;
> >  	int ret;
> > @@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> >  
> >  	attach->dev = dev;
> >  	attach->dmabuf = dmabuf;
> > +	attach->dynamic_mapping = dynamic_mapping;
> >  
> >  	mutex_lock(&dmabuf->lock);
> >  
> > @@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> >  		if (ret)
> >  			goto err_attach;
> >  	}
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	list_add(&attach->node, &dmabuf->attachments);
> > +	dma_resv_unlock(dmabuf->resv);
> >  
> >  	mutex_unlock(&dmabuf->lock);
> >  
> > +	/* When either the importer or the exporter can't handle dynamic
> > +	 * mappings we cache the mapping here to avoid issues with the
> > +	 * reservation object lock.
> > +	 */
> > +	if (dma_buf_attachment_is_dynamic(attach) !=
> > +	    dma_buf_is_dynamic(dmabuf)) {
> > +		struct sg_table *sgt;
> > +
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_lock(attach->dmabuf->resv, NULL);
> > +
> > +		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
> > +		if (!sgt)
> > +			sgt = ERR_PTR(-ENOMEM);
> > +		if (IS_ERR(sgt)) {
> > +			ret = PTR_ERR(sgt);
> > +			goto err_unlock;
> > +		}
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_unlock(attach->dmabuf->resv);
> > +		attach->sgt = sgt;
> > +		attach->dir = DMA_BIDIRECTIONAL;
> > +	}
> > +
> >  	return attach;
> >  
> >  err_attach:
> >  	kfree(attach);
> >  	mutex_unlock(&dmabuf->lock);
> >  	return ERR_PTR(ret);
> > +
> > +err_unlock:
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_unlock(attach->dmabuf->resv);
> > +
> > +	dma_buf_detach(dmabuf, attach);
> > +	return ERR_PTR(ret);
> > +}
> > +EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
> > +
> > +/**
> > + * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
> > + * @dmabuf:	[in]	buffer to attach device to.
> > + * @dev:	[in]	device to be attached.
> > + *
> > + * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
> > + * mapping.
> > + */
> > +struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> > +					  struct device *dev)
> > +{
> > +	return dma_buf_dynamic_attach(dmabuf, dev, false);
> >  }
> >  EXPORT_SYMBOL_GPL(dma_buf_attach);
> >  
> > @@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
> >  	if (WARN_ON(!dmabuf || !attach))
> >  		return;
> >  
> > -	if (attach->sgt)
> > +	if (attach->sgt) {
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_lock(attach->dmabuf->resv, NULL);
> > +
> >  		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
> >  
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_unlock(attach->dmabuf->resv);
> > +	}
> > +
> >  	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	list_del(&attach->node);
> > +	dma_resv_unlock(dmabuf->resv);
> >  	if (dmabuf->ops->detach)
> >  		dmabuf->ops->detach(dmabuf, attach);
> >  
> > @@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
> >  	if (WARN_ON(!attach || !attach->dmabuf))
> >  		return ERR_PTR(-EINVAL);
> >  
> > +	if (dma_buf_attachment_is_dynamic(attach))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	if (attach->sgt) {
> >  		/*
> >  		 * Two mappings with different directions for the same
> > @@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
> >  		return attach->sgt;
> >  	}
> >  
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> 
> Almost tripped me up until I noticed your check for the buf/exporter here.
> Nice check!
> 
> Maybe we could do an
> 
> 	else
> 		lockdep_assert_not_held()
> 
> here? Open-coded ofc (or put it into drm_utils.h, I don't want to hold up
> this patch any longer, then move it to lockdep.h later on), since
> currently doesn't exist. Just to _really_ enforce the documented contract
> here.

On 2nd thought, probably better to do this as a follow up 2 patch series,
first patch adding the lockdep_assert_not_held to lockdep.h, 2nd one
adding the else here and in the unmap function below. Otherwise we're
going to be stuck in another bikeshed here.

Cheers, Daniel


> 

> > +
> >  	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
> >  	if (!sg_table)
> >  		sg_table = ERR_PTR(-ENOMEM);
> > @@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
> >  	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
> >  		return;
> >  
> > +	if (dma_buf_attachment_is_dynamic(attach))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	if (attach->sgt == sg_table)
> >  		return;
> >  
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
> >  }
> >  EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
> > @@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
> >  		seq_puts(s, "\tAttached Devices:\n");
> >  		attach_count = 0;
> >  
> > +		dma_resv_lock(buf_obj->resv, NULL);
> 
> You've switched dmabuf->name to be protected by dma_resv too, so this
> needs to be moved up above the seq_printf which prints ->name.
> 
> >  		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
> >  			seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
> >  			attach_count++;
> >  		}
> > +		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
> > --- a/include/linux/dma-buf.h
> > +++ b/include/linux/dma-buf.h
> > @@ -42,6 +42,18 @@ struct dma_buf_ops {
> >  	  */
> >  	bool cache_sgt_mapping;
> >  
> > +	/**
> > +	 * @dynamic_mapping:
> > +	 *
> > +	 * If true the framework makes sure that the map/unmap_dma_buf
> > +	 * callbacks are always called with the dma_resv object locked.
> > +	 *
> > +	 * If false the framework makes ure that the map/unmap_dma_buf
> 
> s/ure/sure/
> 
> > +	 * callbacks are always called without the dma_resv object locked.
> > +	 * Mutual exclusive with @cache_sgt_mapping.
> > +	 */
> > +	bool dynamic_mapping;
> > +
> >  	/**
> >  	 * @attach:
> >  	 *
> > @@ -109,6 +121,9 @@ struct dma_buf_ops {
> >  	 * any other kind of sharing that the exporter might wish to make
> >  	 * available to buffer-users.
> >  	 *
> > +	 * This is always called with the dmabuf->resv object locked when
> > +	 * the dynamic_mapping flag is true.
> > +	 *
> >  	 * Returns:
> >  	 *
> >  	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
> > @@ -267,7 +282,8 @@ struct dma_buf_ops {
> >   * struct dma_buf - shared buffer object
> >   * @size: size of the buffer
> >   * @file: file pointer used for sharing buffers across, and for refcounting.
> > - * @attachments: list of dma_buf_attachment that denotes all devices attached.
> > + * @attachments: list of dma_buf_attachment that denotes all devices attached,
> > + *               protected by dma_resv lock.
> >   * @ops: dma_buf_ops associated with this buffer object.
> >   * @lock: used internally to serialize list manipulation, attach/detach and
> >   *        vmap/unmap, and accesses to name
> 
> @name in dma_buf needs to be updated to mention that it's protected by
> dma_resv lock.
> 
> > @@ -323,10 +339,12 @@ struct dma_buf {
> >   * struct dma_buf_attachment - holds device-buffer attachment data
> >   * @dmabuf: buffer for this attachment.
> >   * @dev: device attached to the buffer.
> > - * @node: list of dma_buf_attachment.
> > + * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
> >   * @sgt: cached mapping.
> >   * @dir: direction of cached mapping.
> >   * @priv: exporter specific attachment data.
> > + * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
> > + * dma_resv lock held.
> >   *
> >   * This structure holds the attachment information between the dma_buf buffer
> >   * and its user device(s). The list contains one attachment struct per device
> > @@ -343,6 +361,7 @@ struct dma_buf_attachment {
> >  	struct list_head node;
> >  	struct sg_table *sgt;
> >  	enum dma_data_direction dir;
> > +	bool dynamic_mapping;
> >  	void *priv;
> >  };
> >  
> > @@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
> >  	get_file(dmabuf->file);
> >  }
> >  
> > +/**
> > + * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
> > + * @dmabuf: the DMA-buf to check
> > + *
> > + * Returns true if a DMA-buf exporter wants to be called with the dma_resv
> > + * locked, false if it doesn't wants to be called with the lock held.
> 
> Maybe added "... for the map/unmap callbacks, ..." since we don't
> guarantee to hold the lock for all callbacks. You clarify this already
> below.
> 
> > + */
> > +static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
> > +{
> > +	return dmabuf->ops->dynamic_mapping;
> > +}
> > +
> > +/**
> > + * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
> > + * mappinsg
> > + * @attach: the DMA-buf attachment to check
> > + *
> > + * Returns true if a DMA-buf importer wants to call the map/unmap functions with
> > + * the dma_resv lock held.
> > + */
> > +static inline bool
> > +dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
> > +{
> > +	return attach->dynamic_mapping;
> > +}
> > +
> >  struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> > -							struct device *dev);
> > +					  struct device *dev);
> > +struct dma_buf_attachment *
> > +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> > +		       bool dynamic_mapping);
> >  void dma_buf_detach(struct dma_buf *dmabuf,
> > -				struct dma_buf_attachment *dmabuf_attach);
> > +		    struct dma_buf_attachment *attach);
> >  
> >  struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
> >  
> > @@ -409,6 +457,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_move_notify(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,
> 
> With the nits all addressed:
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > -- 
> > 2.17.1
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/4] dma-buf: change DMA-buf locking convention v2
@ 2019-10-22 10:04     ` Daniel Vetter
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:04 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx, dri-devel, linaro-mm-sig, linux-media

On Tue, Oct 22, 2019 at 12:01:30PM +0200, Daniel Vetter wrote:
> On Mon, Oct 21, 2019 at 01:15:21PM +0200, Christian König wrote:
> > This patch is a stripped down version of the locking changes
> > necessary to support dynamic DMA-buf handling.
> > 
> > It adds a dynamic flag for both importers as well as exporters
> > so that drivers can choose if they want the reservation object
> > locked or unlocked during mapping of attachments.
> > 
> > For compatibility between drivers we cache the DMA-buf mapping
> > during attaching an importer as soon as exporter/importer
> > disagree on the dynamic handling.
> > 
> > This change has gone through a lengthy discussion on dri-devel
> > and other mailing lists with at least 3-4 different attempts and
> > dead-ends until we settled on this solution. Please refer to the
> > mailing lists archives for full background on the history of
> > this change.

Two more refinments below, I hit send a notch too early.
> 
> I kinda hoped for a real write-up of why we ended up here, not a "please
> read the last year or so of dri-devel" ...
> 
> So here's what I think we need to minimally mention, pls add:
> 
> <cut>
> Issues and solutions we considered:
> 
> - We can't change all existing drivers, and existing drivers have strong
>   opinions about which locks they're holding while calling
>   dma_buf_attachment_map/unmap. The solution to avoid this was to move the

Maybe add here "Exporters also have strong opinions about which locks they
can acquire in their ->map/unmap callbacks, levaing no room for change."

>   actual map/unmap out from this call, into the attach/detach callbacks,
>   and cache the mapping. This works because drivers don't call
>   attach/detach from deep within their code callchains (like deep in
>   memory management code called from cs/execbuf ioctl), but directly from
>   the fd2handle implementation.
> 
> - The caching has some troubles on some soc drivers, which set other modes
>   than DMA_BIDIRECTIONAL. We can't have 2 incompatible mappings, and we
>   can't re-create the mapping at _map time due to the above locking fun.
>   We very carefuly step around that by only caching at attach time if the
>   dynamic mode between importer/expoert mismatches.
> 
> - There's been quite some discussion on dma-buf mappings which need active
>   cache management, which would all break down when caching, plus we don't
>   have explicit flush operations on the attachment side. The solution to
>   this was to shrug and keep the current discrepancy between what the
>   dma-buf docs claim and what implementations do, with the hope that the
>   begin/end_cpu_access hooks are good enough and that all necessary
>   flushing to keep device mappings consistent will be done there.
> </cut>
> > 
> > v2: cleanup set_name merge, improve kerneldoc
> > 
> > Signed-off-by: Christian König <christian.koenig@amd.com>
> > ---
> >  drivers/dma-buf/dma-buf.c | 102 +++++++++++++++++++++++++++++++++-----
> >  include/linux/dma-buf.h   |  57 +++++++++++++++++++--
> >  2 files changed, 143 insertions(+), 16 deletions(-)
> > 
> > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> > index 433d91d710e4..753be84b5fd6 100644
> > --- a/drivers/dma-buf/dma-buf.c
> > +++ b/drivers/dma-buf/dma-buf.c
> > @@ -45,10 +45,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
> >  	size_t ret = 0;
> >  
> >  	dmabuf = dentry->d_fsdata;
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (dmabuf->name)
> >  		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  
> >  	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
> >  			     dentry->d_name.name, ret > 0 ? name : "");
> > @@ -334,7 +334,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
> >  	if (IS_ERR(name))
> >  		return PTR_ERR(name);
> >  
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (!list_empty(&dmabuf->attachments)) {
> >  		ret = -EBUSY;
> >  		kfree(name);
> > @@ -344,7 +344,7 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
> >  	dmabuf->name = name;
> >  
> >  out_unlock:
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  	return ret;
> >  }
> >  
> > @@ -403,10 +403,10 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
> >  	/* Don't count the temporary reference taken inside procfs seq_show */
> >  	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
> >  	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
> > -	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	if (dmabuf->name)
> >  		seq_printf(m, "name:\t%s\n", dmabuf->name);
> > -	mutex_unlock(&dmabuf->lock);
> > +	dma_resv_unlock(dmabuf->resv);
> >  }
> >  
> >  static const struct file_operations dma_buf_fops = {
> > @@ -525,6 +525,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> >  		return ERR_PTR(-EINVAL);
> >  	}
> >  
> > +	if (WARN_ON(exp_info->ops->cache_sgt_mapping &&
> > +		    exp_info->ops->dynamic_mapping))
> > +		return ERR_PTR(-EINVAL);
> > +
> >  	if (!try_module_get(exp_info->owner))
> >  		return ERR_PTR(-ENOENT);
> >  
> > @@ -645,10 +649,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
> >  EXPORT_SYMBOL_GPL(dma_buf_put);
> >  
> >  /**
> > - * dma_buf_attach - Add the device to dma_buf's attachments list; optionally,
> > + * dma_buf_dynamic_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.
> > + * @dmabuf:		[in]	buffer to attach device to.
> > + * @dev:		[in]	device to be attached.
> > + * @dynamic_mapping:	[in]	calling convention for map/unmap
> >   *
> >   * Returns struct dma_buf_attachment pointer for this attachment. Attachments
> >   * must be cleaned up by calling dma_buf_detach().
> > @@ -662,8 +667,9 @@ 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_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> > +		       bool dynamic_mapping)
> >  {
> >  	struct dma_buf_attachment *attach;
> >  	int ret;
> > @@ -677,6 +683,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> >  
> >  	attach->dev = dev;
> >  	attach->dmabuf = dmabuf;
> > +	attach->dynamic_mapping = dynamic_mapping;
> >  
> >  	mutex_lock(&dmabuf->lock);
> >  
> > @@ -685,16 +692,64 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> >  		if (ret)
> >  			goto err_attach;
> >  	}
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	list_add(&attach->node, &dmabuf->attachments);
> > +	dma_resv_unlock(dmabuf->resv);
> >  
> >  	mutex_unlock(&dmabuf->lock);
> >  
> > +	/* When either the importer or the exporter can't handle dynamic
> > +	 * mappings we cache the mapping here to avoid issues with the
> > +	 * reservation object lock.
> > +	 */
> > +	if (dma_buf_attachment_is_dynamic(attach) !=
> > +	    dma_buf_is_dynamic(dmabuf)) {
> > +		struct sg_table *sgt;
> > +
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_lock(attach->dmabuf->resv, NULL);
> > +
> > +		sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL);
> > +		if (!sgt)
> > +			sgt = ERR_PTR(-ENOMEM);
> > +		if (IS_ERR(sgt)) {
> > +			ret = PTR_ERR(sgt);
> > +			goto err_unlock;
> > +		}
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_unlock(attach->dmabuf->resv);
> > +		attach->sgt = sgt;
> > +		attach->dir = DMA_BIDIRECTIONAL;
> > +	}
> > +
> >  	return attach;
> >  
> >  err_attach:
> >  	kfree(attach);
> >  	mutex_unlock(&dmabuf->lock);
> >  	return ERR_PTR(ret);
> > +
> > +err_unlock:
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_unlock(attach->dmabuf->resv);
> > +
> > +	dma_buf_detach(dmabuf, attach);
> > +	return ERR_PTR(ret);
> > +}
> > +EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach);
> > +
> > +/**
> > + * dma_buf_attach - Wrapper for dma_buf_dynamic_attach
> > + * @dmabuf:	[in]	buffer to attach device to.
> > + * @dev:	[in]	device to be attached.
> > + *
> > + * Wrapper to call dma_buf_dynamic_attach() for drivers which still use a static
> > + * mapping.
> > + */
> > +struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> > +					  struct device *dev)
> > +{
> > +	return dma_buf_dynamic_attach(dmabuf, dev, false);
> >  }
> >  EXPORT_SYMBOL_GPL(dma_buf_attach);
> >  
> > @@ -711,11 +766,20 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
> >  	if (WARN_ON(!dmabuf || !attach))
> >  		return;
> >  
> > -	if (attach->sgt)
> > +	if (attach->sgt) {
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_lock(attach->dmabuf->resv, NULL);
> > +
> >  		dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir);
> >  
> > +		if (dma_buf_is_dynamic(attach->dmabuf))
> > +			dma_resv_unlock(attach->dmabuf->resv);
> > +	}
> > +
> >  	mutex_lock(&dmabuf->lock);
> > +	dma_resv_lock(dmabuf->resv, NULL);
> >  	list_del(&attach->node);
> > +	dma_resv_unlock(dmabuf->resv);
> >  	if (dmabuf->ops->detach)
> >  		dmabuf->ops->detach(dmabuf, attach);
> >  
> > @@ -749,6 +813,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
> >  	if (WARN_ON(!attach || !attach->dmabuf))
> >  		return ERR_PTR(-EINVAL);
> >  
> > +	if (dma_buf_attachment_is_dynamic(attach))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	if (attach->sgt) {
> >  		/*
> >  		 * Two mappings with different directions for the same
> > @@ -761,6 +828,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
> >  		return attach->sgt;
> >  	}
> >  
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> 
> Almost tripped me up until I noticed your check for the buf/exporter here.
> Nice check!
> 
> Maybe we could do an
> 
> 	else
> 		lockdep_assert_not_held()
> 
> here? Open-coded ofc (or put it into drm_utils.h, I don't want to hold up
> this patch any longer, then move it to lockdep.h later on), since
> currently doesn't exist. Just to _really_ enforce the documented contract
> here.

On 2nd thought, probably better to do this as a follow up 2 patch series,
first patch adding the lockdep_assert_not_held to lockdep.h, 2nd one
adding the else here and in the unmap function below. Otherwise we're
going to be stuck in another bikeshed here.

Cheers, Daniel


> 

> > +
> >  	sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction);
> >  	if (!sg_table)
> >  		sg_table = ERR_PTR(-ENOMEM);
> > @@ -793,9 +863,15 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
> >  	if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
> >  		return;
> >  
> > +	if (dma_buf_attachment_is_dynamic(attach))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	if (attach->sgt == sg_table)
> >  		return;
> >  
> > +	if (dma_buf_is_dynamic(attach->dmabuf))
> > +		dma_resv_assert_held(attach->dmabuf->resv);
> > +
> >  	attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
> >  }
> >  EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
> > @@ -1219,10 +1295,12 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
> >  		seq_puts(s, "\tAttached Devices:\n");
> >  		attach_count = 0;
> >  
> > +		dma_resv_lock(buf_obj->resv, NULL);
> 
> You've switched dmabuf->name to be protected by dma_resv too, so this
> needs to be moved up above the seq_printf which prints ->name.
> 
> >  		list_for_each_entry(attach_obj, &buf_obj->attachments, node) {
> >  			seq_printf(s, "\t%s\n", dev_name(attach_obj->dev));
> >  			attach_count++;
> >  		}
> > +		dma_resv_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 ec212cb27fdc..bcc0f4d0b678 100644
> > --- a/include/linux/dma-buf.h
> > +++ b/include/linux/dma-buf.h
> > @@ -42,6 +42,18 @@ struct dma_buf_ops {
> >  	  */
> >  	bool cache_sgt_mapping;
> >  
> > +	/**
> > +	 * @dynamic_mapping:
> > +	 *
> > +	 * If true the framework makes sure that the map/unmap_dma_buf
> > +	 * callbacks are always called with the dma_resv object locked.
> > +	 *
> > +	 * If false the framework makes ure that the map/unmap_dma_buf
> 
> s/ure/sure/
> 
> > +	 * callbacks are always called without the dma_resv object locked.
> > +	 * Mutual exclusive with @cache_sgt_mapping.
> > +	 */
> > +	bool dynamic_mapping;
> > +
> >  	/**
> >  	 * @attach:
> >  	 *
> > @@ -109,6 +121,9 @@ struct dma_buf_ops {
> >  	 * any other kind of sharing that the exporter might wish to make
> >  	 * available to buffer-users.
> >  	 *
> > +	 * This is always called with the dmabuf->resv object locked when
> > +	 * the dynamic_mapping flag is true.
> > +	 *
> >  	 * Returns:
> >  	 *
> >  	 * A &sg_table scatter list of or the backing storage of the DMA buffer,
> > @@ -267,7 +282,8 @@ struct dma_buf_ops {
> >   * struct dma_buf - shared buffer object
> >   * @size: size of the buffer
> >   * @file: file pointer used for sharing buffers across, and for refcounting.
> > - * @attachments: list of dma_buf_attachment that denotes all devices attached.
> > + * @attachments: list of dma_buf_attachment that denotes all devices attached,
> > + *               protected by dma_resv lock.
> >   * @ops: dma_buf_ops associated with this buffer object.
> >   * @lock: used internally to serialize list manipulation, attach/detach and
> >   *        vmap/unmap, and accesses to name
> 
> @name in dma_buf needs to be updated to mention that it's protected by
> dma_resv lock.
> 
> > @@ -323,10 +339,12 @@ struct dma_buf {
> >   * struct dma_buf_attachment - holds device-buffer attachment data
> >   * @dmabuf: buffer for this attachment.
> >   * @dev: device attached to the buffer.
> > - * @node: list of dma_buf_attachment.
> > + * @node: list of dma_buf_attachment, protected by dma_resv lock of the dmabuf.
> >   * @sgt: cached mapping.
> >   * @dir: direction of cached mapping.
> >   * @priv: exporter specific attachment data.
> > + * @dynamic_mapping: true if dma_buf_map/unmap_attachment() is called with the
> > + * dma_resv lock held.
> >   *
> >   * This structure holds the attachment information between the dma_buf buffer
> >   * and its user device(s). The list contains one attachment struct per device
> > @@ -343,6 +361,7 @@ struct dma_buf_attachment {
> >  	struct list_head node;
> >  	struct sg_table *sgt;
> >  	enum dma_data_direction dir;
> > +	bool dynamic_mapping;
> >  	void *priv;
> >  };
> >  
> > @@ -394,10 +413,39 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
> >  	get_file(dmabuf->file);
> >  }
> >  
> > +/**
> > + * dma_buf_is_dynamic - check if a DMA-buf uses dynamic mappings.
> > + * @dmabuf: the DMA-buf to check
> > + *
> > + * Returns true if a DMA-buf exporter wants to be called with the dma_resv
> > + * locked, false if it doesn't wants to be called with the lock held.
> 
> Maybe added "... for the map/unmap callbacks, ..." since we don't
> guarantee to hold the lock for all callbacks. You clarify this already
> below.
> 
> > + */
> > +static inline bool dma_buf_is_dynamic(struct dma_buf *dmabuf)
> > +{
> > +	return dmabuf->ops->dynamic_mapping;
> > +}
> > +
> > +/**
> > + * dma_buf_attachment_is_dynamic - check if a DMA-buf attachment uses dynamic
> > + * mappinsg
> > + * @attach: the DMA-buf attachment to check
> > + *
> > + * Returns true if a DMA-buf importer wants to call the map/unmap functions with
> > + * the dma_resv lock held.
> > + */
> > +static inline bool
> > +dma_buf_attachment_is_dynamic(struct dma_buf_attachment *attach)
> > +{
> > +	return attach->dynamic_mapping;
> > +}
> > +
> >  struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
> > -							struct device *dev);
> > +					  struct device *dev);
> > +struct dma_buf_attachment *
> > +dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
> > +		       bool dynamic_mapping);
> >  void dma_buf_detach(struct dma_buf *dmabuf,
> > -				struct dma_buf_attachment *dmabuf_attach);
> > +		    struct dma_buf_attachment *attach);
> >  
> >  struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
> >  
> > @@ -409,6 +457,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_move_notify(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,
> 
> With the nits all addressed:
> 
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> > -- 
> > 2.17.1
> > 
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/4] dma-buf: stop using the dmabuf->lock so much
  2019-10-21 11:15   ` Christian König
@ 2019-10-22 10:13     ` Daniel Vetter
  -1 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:13 UTC (permalink / raw)
  To: Christian König
  Cc: dri-devel, sumit.semwal, linaro-mm-sig, linux-media, intel-gfx, daniel

On Mon, Oct 21, 2019 at 01:15:22PM +0200, Christian König wrote:
> The attachment list is now protected by the dma_resv object.
> So we can drop holding this lock to allow concurrent attach
> and detach operations.
> 
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/dma-buf/dma-buf.c | 16 ----------------
>  1 file changed, 16 deletions(-)
> 
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 753be84b5fd6..c736e67ae1a1 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -685,8 +685,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  	attach->dmabuf = dmabuf;
>  	attach->dynamic_mapping = dynamic_mapping;
>  
> -	mutex_lock(&dmabuf->lock);
> -
>  	if (dmabuf->ops->attach) {
>  		ret = dmabuf->ops->attach(dmabuf, attach);
>  		if (ret)
> @@ -696,8 +694,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  	list_add(&attach->node, &dmabuf->attachments);
>  	dma_resv_unlock(dmabuf->resv);
>  
> -	mutex_unlock(&dmabuf->lock);

This changes the rules, now ->attach/->detach and the list manipulation
aren't done under the same lock anymore. I don't think this matters, but
imo good to mention in the commit message.

> -
>  	/* When either the importer or the exporter can't handle dynamic
>  	 * mappings we cache the mapping here to avoid issues with the
>  	 * reservation object lock.
> @@ -726,7 +722,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  
>  err_attach:
>  	kfree(attach);
> -	mutex_unlock(&dmabuf->lock);
>  	return ERR_PTR(ret);
>  
>  err_unlock:
> @@ -776,14 +771,12 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
>  			dma_resv_unlock(attach->dmabuf->resv);
>  	}
>  
> -	mutex_lock(&dmabuf->lock);
>  	dma_resv_lock(dmabuf->resv, NULL);
>  	list_del(&attach->node);
>  	dma_resv_unlock(dmabuf->resv);
>  	if (dmabuf->ops->detach)
>  		dmabuf->ops->detach(dmabuf, attach);
>  
> -	mutex_unlock(&dmabuf->lock);
>  	kfree(attach);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_detach);
> @@ -1247,14 +1240,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  		   "size", "flags", "mode", "count", "ino");
>  
>  	list_for_each_entry(buf_obj, &db_list.head, list_node) {
> -		ret = mutex_lock_interruptible(&buf_obj->lock);
> -
> -		if (ret) {
> -			seq_puts(s,
> -				 "\tERROR locking buffer object: skipping\n");
> -			continue;
> -		}
> -

This will mildly conflict with the revised version of patch 1 (since the
dma_resv_lock needs to be here).

With both nits addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
>  				buf_obj->size,
>  				buf_obj->file->f_flags, buf_obj->file->f_mode,
> @@ -1307,7 +1292,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  
>  		count++;
>  		size += buf_obj->size;
> -		mutex_unlock(&buf_obj->lock);
>  	}
>  
>  	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
> -- 
> 2.17.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/4] dma-buf: stop using the dmabuf->lock so much
@ 2019-10-22 10:13     ` Daniel Vetter
  0 siblings, 0 replies; 18+ messages in thread
From: Daniel Vetter @ 2019-10-22 10:13 UTC (permalink / raw)
  To: Christian König; +Cc: intel-gfx, dri-devel, linaro-mm-sig, linux-media

On Mon, Oct 21, 2019 at 01:15:22PM +0200, Christian König wrote:
> The attachment list is now protected by the dma_resv object.
> So we can drop holding this lock to allow concurrent attach
> and detach operations.
> 
> Signed-off-by: Christian König <christian.koenig@amd.com>
> ---
>  drivers/dma-buf/dma-buf.c | 16 ----------------
>  1 file changed, 16 deletions(-)
> 
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 753be84b5fd6..c736e67ae1a1 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -685,8 +685,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  	attach->dmabuf = dmabuf;
>  	attach->dynamic_mapping = dynamic_mapping;
>  
> -	mutex_lock(&dmabuf->lock);
> -
>  	if (dmabuf->ops->attach) {
>  		ret = dmabuf->ops->attach(dmabuf, attach);
>  		if (ret)
> @@ -696,8 +694,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  	list_add(&attach->node, &dmabuf->attachments);
>  	dma_resv_unlock(dmabuf->resv);
>  
> -	mutex_unlock(&dmabuf->lock);

This changes the rules, now ->attach/->detach and the list manipulation
aren't done under the same lock anymore. I don't think this matters, but
imo good to mention in the commit message.

> -
>  	/* When either the importer or the exporter can't handle dynamic
>  	 * mappings we cache the mapping here to avoid issues with the
>  	 * reservation object lock.
> @@ -726,7 +722,6 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
>  
>  err_attach:
>  	kfree(attach);
> -	mutex_unlock(&dmabuf->lock);
>  	return ERR_PTR(ret);
>  
>  err_unlock:
> @@ -776,14 +771,12 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
>  			dma_resv_unlock(attach->dmabuf->resv);
>  	}
>  
> -	mutex_lock(&dmabuf->lock);
>  	dma_resv_lock(dmabuf->resv, NULL);
>  	list_del(&attach->node);
>  	dma_resv_unlock(dmabuf->resv);
>  	if (dmabuf->ops->detach)
>  		dmabuf->ops->detach(dmabuf, attach);
>  
> -	mutex_unlock(&dmabuf->lock);
>  	kfree(attach);
>  }
>  EXPORT_SYMBOL_GPL(dma_buf_detach);
> @@ -1247,14 +1240,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  		   "size", "flags", "mode", "count", "ino");
>  
>  	list_for_each_entry(buf_obj, &db_list.head, list_node) {
> -		ret = mutex_lock_interruptible(&buf_obj->lock);
> -
> -		if (ret) {
> -			seq_puts(s,
> -				 "\tERROR locking buffer object: skipping\n");
> -			continue;
> -		}
> -

This will mildly conflict with the revised version of patch 1 (since the
dma_resv_lock needs to be here).

With both nits addressed:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  		seq_printf(s, "%08zu\t%08x\t%08x\t%08ld\t%s\t%08lu\t%s\n",
>  				buf_obj->size,
>  				buf_obj->file->f_flags, buf_obj->file->f_mode,
> @@ -1307,7 +1292,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
>  
>  		count++;
>  		size += buf_obj->size;
> -		mutex_unlock(&buf_obj->lock);
>  	}
>  
>  	seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size);
> -- 
> 2.17.1
> 

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-10-22 10:13 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-21 11:15 [PATCH 1/4] dma-buf: change DMA-buf locking convention v2 Christian König
2019-10-21 11:15 ` Christian König
2019-10-21 11:15 ` [PATCH 2/4] dma-buf: stop using the dmabuf->lock so much Christian König
2019-10-21 11:15   ` Christian König
2019-10-22 10:13   ` Daniel Vetter
2019-10-22 10:13     ` Daniel Vetter
2019-10-21 11:15 ` [PATCH 3/4] drm/amdgpu: add independent DMA-buf export v7 Christian König
2019-10-21 11:15   ` Christian König
2019-10-21 11:15 ` [PATCH 4/4] drm/amdgpu: add independent DMA-buf import v8 Christian König
2019-10-21 11:15   ` Christian König
2019-10-21 21:48 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/4] dma-buf: change DMA-buf locking convention v2 Patchwork
2019-10-21 21:50 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-10-21 22:13 ` ✓ Fi.CI.BAT: success " Patchwork
2019-10-22  6:46 ` ✗ Fi.CI.IGT: failure " Patchwork
2019-10-22 10:01 ` [PATCH 1/4] " Daniel Vetter
2019-10-22 10:01   ` Daniel Vetter
2019-10-22 10:04   ` Daniel Vetter
2019-10-22 10:04     ` Daniel Vetter

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.