implicit drm synchronization wip with dma-buf
Subsystems (3)
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 gpulist_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
@@ -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
@@ -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
@@ -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; };/**