External clients which import our bo's wait only
for exclusive dmabuf-fences, not on shared ones,
so attach fences on such exported buffers as
exclusive ones.

See discussion in thread:
https://lists.freedesktop.org/archives/dri-devel/2016-October/122370.html

Tested on Intel iGPU + AMD Tonga dGPU as DRI3/Present
Prime render offload, and with the Tonga standalone as
primary gpu.

v2: Add a wait for all shared fences before prime export,
    as suggested by Christian Koenig.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95472
(v1) Tested-by: Mike Lothian <mike at fireburn.co.uk>
Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
Cc: Christian König <christian.koenig at amd.com>
Cc: Michel Dänzer <michel.daenzer at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h         |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c   | 11 +++++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 039b57e..a337d56 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -459,6 +459,7 @@ struct amdgpu_bo {
        u64                             metadata_flags;
        void                            *metadata;
        u32                             metadata_size;
+       bool                            prime_exported;
        /* list of all virtual address to which this bo
         * is associated to
         */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
index 651115d..51c6f60 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -132,7 +132,7 @@ static int amdgpu_bo_list_set(struct amdgpu_device *adev,
                entry->priority = min(info[i].bo_priority,
                                      AMDGPU_BO_LIST_MAX_PRIORITY);
                entry->tv.bo = &entry->robj->tbo;
-               entry->tv.shared = true;
+               entry->tv.shared = !entry->robj->prime_exported;

                if (entry->robj->prefered_domains == AMDGPU_GEM_DOMAIN_GDS)
                        gds_obj = entry->robj;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
index 7700dc2..0ed92a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
@@ -117,9 +117,20 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device 
*dev,
                                        int flags)
 {
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj);
+       long ret;

        if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm))
                return ERR_PTR(-EPERM);

+       /*
+        * Wait for all shared fences to complete before we switch to future
+        * use of exclusive fence on this prime_exported bo.
+        */
+       ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false,
+                                                 MAX_SCHEDULE_TIMEOUT);
+       WARN(ret <= 0, "Fence wait returns %li\n", ret);
+
+       bo->prime_exported = true;
+
        return drm_gem_prime_export(dev, gobj, flags);
 }
-- 
2.7.4

Reply via email to