If the GEM objects being rendered with in this request have been
exported via dma-buf to a third party, hook ourselves into the dma-buf
reservation object so that the third party can serialise with our
rendering via the dma-buf fences.

Testcase: igt/prime_busy
Signed-off-by: Chris Wilson <[email protected]>
---
 drivers/gpu/drm/i915/i915_gem_dmabuf.c     | 40 +++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 30 ++++++++++++++++++++--
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c 
b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index 80bbe43a2e92..8a5f88aef6e8 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -23,9 +23,13 @@
  * Authors:
  *     Dave Airlie <[email protected]>
  */
+
+#include <linux/dma-buf.h>
+#include <linux/reservation.h>
+
 #include <drm/drmP.h>
+
 #include "i915_drv.h"
-#include <linux/dma-buf.h>
 
 static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
 {
@@ -218,25 +222,55 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
        .end_cpu_access = i915_gem_end_cpu_access,
 };
 
+static void export_fences(struct drm_i915_gem_object *obj,
+                         struct dma_buf *dma_buf)
+{
+       struct reservation_object *resv = dma_buf->resv;
+       struct drm_i915_gem_request *req;
+       int idx;
+
+       mutex_lock(&obj->base.dev->struct_mutex);
+
+       for (idx = 0; idx < ARRAY_SIZE(obj->last_read_req); idx++) {
+               req = obj->last_read_req[idx];
+               if (!req)
+                       continue;
+
+               if (reservation_object_reserve_shared(resv) == 0)
+                       reservation_object_add_shared_fence(resv, &req->fence);
+       }
+
+       req = obj->last_write_req;
+       if (req)
+               reservation_object_add_excl_fence(resv, &req->fence);
+
+       mutex_unlock(&obj->base.dev->struct_mutex);
+}
+
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                                      struct drm_gem_object *gem_obj, int flags)
 {
        struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
        DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+       struct dma_buf *dma_buf;
 
        exp_info.ops = &i915_dmabuf_ops;
        exp_info.size = gem_obj->size;
        exp_info.flags = flags;
        exp_info.priv = gem_obj;
 
-
        if (obj->ops->dmabuf_export) {
                int ret = obj->ops->dmabuf_export(obj);
                if (ret)
                        return ERR_PTR(ret);
        }
 
-       return dma_buf_export(&exp_info);
+       dma_buf = dma_buf_export(&exp_info);
+       if (IS_ERR(dma_buf))
+               return dma_buf;
+
+       export_fences(obj, dma_buf);
+       return dma_buf;
 }
 
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 39c53d97833a..1cc4ba7e87a4 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -26,13 +26,17 @@
  *
  */
 
+#include <linux/dma_remapping.h>
+#include <linux/reservation.h>
+#include <linux/uaccess.h>
+
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
+
 #include "i915_drv.h"
+#include "i915_gem_dmabuf.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
-#include <linux/dma_remapping.h>
-#include <linux/uaccess.h>
 
 #define  __EXEC_OBJECT_HAS_PIN (1<<31)
 #define  __EXEC_OBJECT_HAS_FENCE (1<<30)
@@ -1086,6 +1090,27 @@ i915_gem_validate_context(struct drm_device *dev, struct 
drm_file *file,
        return ctx;
 }
 
+static void eb_export_fence(struct drm_i915_gem_object *obj,
+                           struct drm_i915_gem_request *req)
+{
+       struct reservation_object *resv;
+
+       resv = i915_gem_object_get_dmabuf_resv(obj);
+       if (!resv)
+               return;
+
+       /* Ignore errors from failing to allocate the new fence, we can't
+        * handle an error right now. Worst case should be missed
+        * synchronisation leading to rendering corruption.
+        */
+       mutex_lock(&resv->lock.base);
+       if (obj->base.write_domain)
+               reservation_object_add_excl_fence(resv, &req->fence);
+       else if (reservation_object_reserve_shared(resv) == 0)
+               reservation_object_add_shared_fence(resv, &req->fence);
+       mutex_unlock(&resv->lock.base);
+}
+
 void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                                   struct drm_i915_gem_request *req)
@@ -1106,6 +1131,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
                obj->base.read_domains = obj->base.pending_read_domains;
 
                i915_vma_move_to_active(vma, req);
+               eb_export_fence(obj, req);
                if (obj->base.write_domain) {
                        i915_gem_request_assign(&obj->last_write_req, req);
 
-- 
2.8.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to