Message ID | 1478654715-22334-1-git-send-email-mario.kleiner.de@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi I've tested this version now - works great Thanks Mike On Wed, 9 Nov 2016 at 01:26 Mario Kleiner <mario.kleiner.de@gmail.com> wrote: > External clients which import our bo's wait only > for exclusive dmabuf-fences, not on shared ones, > ditto for bo's which we import from external > providers and write to. > > Therefore attach exclusive fences on prime shared buffers > if our exported buffer gets imported by an external > client, or if we import a buffer from an external > exporter. > > See discussion in thread: > https://lists.freedesktop.org/archives/dri-devel/2016-October/122370.html > > Prime export 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. > > v3: - Mark buffer prime_exported in amdgpu_gem_prime_pin, > so we only use the exclusive fence when exporting a > bo to external clients like a separate iGPU, but not > when exporting/importing from/to ourselves as part of > regular DRI3 fd passing. > > - Propagate failure of reservation_object_wait_rcu back > to caller. > > v4: - Switch to a prime_shared_count counter instead of a > flag, which gets in/decremented on prime_pin/unpin, so > we can switch back to shared fences if all clients > detach from our exported bo. > > - Also switch to exclusive fence for prime imported bo's. > > v5: - Drop lret, instead use int ret -> long ret, as proposed > by Christian. > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=95472 > Tested-by: Mike Lothian <mike@fireburn.co.uk> (v1) > Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> > Reviewed-by: Christian König <christian.koenig@amd.com>. > Cc: Christian König <christian.koenig@amd.com> > Cc: Michel Dänzer <michel.daenzer@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 | 20 +++++++++++++++++++- > 3 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu.h > index 039b57e..496f72b 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; > + unsigned prime_shared_count; > /* 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..c02db01f6 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_shared_count; > > 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..3826d5a 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c > @@ -74,20 +74,36 @@ amdgpu_gem_prime_import_sg_table(struct drm_device > *dev, > if (ret) > return ERR_PTR(ret); > > + bo->prime_shared_count = 1; > return &bo->gem_base; > } > > int amdgpu_gem_prime_pin(struct drm_gem_object *obj) > { > struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); > - int ret = 0; > + long ret = 0; > > ret = amdgpu_bo_reserve(bo, false); > if (unlikely(ret != 0)) > return ret; > > + /* > + * Wait for all shared fences to complete before we switch to > future > + * use of exclusive fence on this prime shared bo. > + */ > + ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, > false, > + MAX_SCHEDULE_TIMEOUT); > + if (unlikely(ret < 0)) { > + DRM_DEBUG_PRIME("Fence wait failed: %li\n", ret); > + amdgpu_bo_unreserve(bo); > + return ret; > + } > + > /* pin buffer into GTT */ > ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL); > + if (likely(ret == 0)) > + bo->prime_shared_count++; > + > amdgpu_bo_unreserve(bo); > return ret; > } > @@ -102,6 +118,8 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj) > return; > > amdgpu_bo_unpin(bo); > + if (bo->prime_shared_count) > + bo->prime_shared_count--; > amdgpu_bo_unreserve(bo); > } > > -- > 2.7.0 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel >
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 039b57e..496f72b 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; + unsigned prime_shared_count; /* 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..c02db01f6 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_shared_count; 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..3826d5a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -74,20 +74,36 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, if (ret) return ERR_PTR(ret); + bo->prime_shared_count = 1; return &bo->gem_base; } int amdgpu_gem_prime_pin(struct drm_gem_object *obj) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - int ret = 0; + long ret = 0; ret = amdgpu_bo_reserve(bo, false); if (unlikely(ret != 0)) return ret; + /* + * Wait for all shared fences to complete before we switch to future + * use of exclusive fence on this prime shared bo. + */ + ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, true, false, + MAX_SCHEDULE_TIMEOUT); + if (unlikely(ret < 0)) { + DRM_DEBUG_PRIME("Fence wait failed: %li\n", ret); + amdgpu_bo_unreserve(bo); + return ret; + } + /* pin buffer into GTT */ ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT, NULL); + if (likely(ret == 0)) + bo->prime_shared_count++; + amdgpu_bo_unreserve(bo); return ret; } @@ -102,6 +118,8 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj) return; amdgpu_bo_unpin(bo); + if (bo->prime_shared_count) + bo->prime_shared_count--; amdgpu_bo_unreserve(bo); }