Skip to contentSkip to conversation

implicit drm synchronization wip with dma-buf

RFC New Maarten Lankhorst 1 participant 1 message Jul 2, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC v2 1/1 implicit drm synchronization wip with dma-buf

Well,

V2 time! I was hinted to look at ttm_execbuf_util, and it does indeed contain some nice code. My goal was to extend dma-buf in a generic way now, some elements from v1 are remaining, most notably a dma-buf used for syncing. However it is expected now that dma-buf syncing will work in a very specific way now, slightly more strict than in v1.

Instead of each buffer having their own dma-buf I put in 1 per command submission.

This submission hasn't been run-time tested yet, but I expect the api to go something like this.

Intended to be used like this:

list_init(&head);
add_list_tail(&validate1->entry, &head);
add_list_tail(&validate2->entry, &head);
add_list_tail(&validate3->entry, &head);

r = dmabufmgr_eu_reserve_buffers(&head);
if (r) return r;

// add waits on cpu or gpu
list_for_each_entry(validate, ...) {

	if (!validate->sync_buf)
		continue;

	// Check attachments to see if we already imported sync_buf
	// somewhere, if not attach to it.
	// waiting until cur_seq - dmabuf->sync_val >= 0 on either cpu
	// or as command submitted to gpu
	// sync_buf itself is a dma-buf, so it should be trivial
	// TODO: sync_buf should NEVER be validated, add is_sync_buf to dma_buf?

	// If this step fails: dmabufmgr_eu_backoff_reservation
	// else:
	// dmabufmgr_eu_fence_buffer_objects(our_own_sync_buf,
	// hwchannel * max(minhwalign, 4), ++counter[hwchannel]);

	// XXX: Do we still require a minimum alignment? I set up 16 for nouveau,
	// but this is no longer needed in this design since it only matters
	// for writes for which nouveau would already control the offset.
}

// Some time after execbuffer was executed, doesn't have to be right away but before // getting in the danger of our own counter wrapping around:

	// grab dmabufmgr.lru_lock, and cleanup by unreffing sync_buf when
	// sync_buf == ownbuf, sync_ofs == ownofs, and sync_val == saved_counter
	// In the meantime someone else or even us might have reserved this dma_buf
	// again, which is why all those checks are needed before unreffing.
drivers/base/Makefile +1 -1
index 5aa2d70..86e7598 100644
@@ -10,7 +10,7 @@ obj-$(CONFIG_CMA) += dma-contiguous.o
 obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o
+obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o dma-buf-mgr.o dma-buf-mgr-eu.o
 obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
drivers/base/dma-buf-mgr-eu.c new file +170 -0

170 lines not on this page · raw message

drivers/base/dma-buf-mgr.c new file +149 -0

149 lines not on this page · raw message

drivers/base/dma-buf.c +4 -0
index 24e88fe..01c4f71 100644
@@ -40,6 +40,9 @@ static int dma_buf_release(struct inode *inode, struct file *file)
 	dmabuf = file->private_data;
 
 	dmabuf->ops->release(dmabuf);
+	BUG_ON(waitqueue_active(&dmabuf->event_queue));
+	if (dmabuf->sync_buf)
+		dma_buf_put(dmabuf->sync_buf);
 	kfree(dmabuf);
 	return 0;
 }
@@ -119,6 +122,7 @@ struct dma_buf *dma_buf_export(void *priv, const struct dma_buf_ops *ops,
 
 	mutex_init(&dmabuf->lock);
 	INIT_LIST_HEAD(&dmabuf->attachments);
+	init_waitqueue_head(&dmabuf->event_queue);
 
 	return dmabuf;
 }
include/linux/dma-buf-mgr.h new file +84 -0

84 lines not on this page · raw message

include/linux/dma-buf.h +20 -0
index eb48f38..b2ab395 100644
@@ -113,6 +113,8 @@ struct dma_buf_ops {
  * @attachments: list of dma_buf_attachment that denotes all devices attached.
  * @ops: dma_buf_ops associated with this buffer object.
  * @priv: exporter specific private data for this buffer object.
+ * @bufmgr_entry: used by dmabufmgr
+ * @bufdev: used by dmabufmgr
  */
 struct dma_buf {
 	size_t size;
@@ -122,6 +124,24 @@ struct dma_buf {
 	/* mutex to serialize list manipulation and attach/detach */
 	struct mutex lock;
 	void *priv;
+
+	/** dmabufmgr members */
+	wait_queue_head_t event_queue;
+
+	/**
+	 * dmabufmgr members protected by the dmabufmgr::lru_lock.
+	 */
+	u32 val_seq;
+	bool seq_valid;
+
+	struct dma_buf *sync_buf;
+	u32 sync_ofs, sync_val;
+
+	/**
+	 * dmabufmgr members protected by the dmabufmgr::lru_lock
+	 * only when written to.
+	 */
+	atomic_t reserved;
 };
 
 /**