diff mbox

drm/amdgpu: Attach exclusive fence to prime exported bo's. (v2)

Message ID 1478307379-17697-1-git-send-email-mario.kleiner.de@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mario Kleiner Nov. 5, 2016, 12:56 a.m. UTC
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@fireburn.co.uk>
Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.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   | 11 +++++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

Comments

Christian König Nov. 5, 2016, 12:06 p.m. UTC | #1
Am 05.11.2016 um 01:56 schrieb Mario Kleiner:
> 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@fireburn.co.uk>
> Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.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   | 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;
> +

As Michel noted as well this is the wrong function for this, cause this 
is used for buffer sharing without DMA-buf as well. Try to put it into 
amdgpu_gem_prime_pin() instead.

I would also improve the error handling so that we return the error when 
the wait failed.

Apart from that this looks really good to me.

Regards,
Christian.

>   	return drm_gem_prime_export(dev, gobj, flags);
>   }
Mario Kleiner Nov. 5, 2016, 5:57 p.m. UTC | #2
On 11/05/2016 01:06 PM, Christian König wrote:
> Am 05.11.2016 um 01:56 schrieb Mario Kleiner:
>> 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@fireburn.co.uk>
>> Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.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   | 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;
>> +
>
> As Michel noted as well this is the wrong function for this, cause this
> is used for buffer sharing without DMA-buf as well. Try to put it into
> amdgpu_gem_prime_pin() instead.
>
> I would also improve the error handling so that we return the error when
> the wait failed.
>

Ok. I'll place the code before the actual pinning code in that function 
then, so it can error out early if needed.

-mario

> Apart from that this looks really good to me.
>
> Regards,
> Christian.
>
>>       return drm_gem_prime_export(dev, gobj, flags);
>>   }
>
>
diff mbox

Patch

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);
 }