linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] drm/amd/amdgpu: get rid of else branch
@ 2017-04-27 16:17 Nikola Pajkovsky
  2017-04-28  8:30 ` Christian König
  0 siblings, 1 reply; 4+ messages in thread
From: Nikola Pajkovsky @ 2017-04-27 16:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alex Deucher, Christian König, David Airlie, amd-gfx, dri-devel

This is super simple elimination of else branch and I should
probably even use unlikely in

 	if (ring->count_dw < count_dw) {

However, amdgpu_ring_write() has similar if condition, but does not
return after DRM_ERROR and it looks suspicious. On error, we still
adding v to ring and keeping count_dw-- below zero.

	if (ring->count_dw <= 0)
		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
	ring->ring[ring->wptr++] = v;
	ring->wptr &= ring->ptr_mask;
	ring->count_dw--;

I can obviously be totaly wrong. Hmm?

--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index c1b913541739..c6f4f874ea68 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1596,28 +1596,29 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, void *sr
 
 	if (ring->count_dw < count_dw) {
 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
-	} else {
-		occupied = ring->wptr & ring->ptr_mask;
-		dst = (void *)&ring->ring[occupied];
-		chunk1 = ring->ptr_mask + 1 - occupied;
-		chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
-		chunk2 = count_dw - chunk1;
-		chunk1 <<= 2;
-		chunk2 <<= 2;
-
-		if (chunk1)
-			memcpy(dst, src, chunk1);
-
-		if (chunk2) {
-			src += chunk1;
-			dst = (void *)ring->ring;
-			memcpy(dst, src, chunk2);
-		}
-
-		ring->wptr += count_dw;
-		ring->wptr &= ring->ptr_mask;
-		ring->count_dw -= count_dw;
+		return;
 	}
+
+	occupied = ring->wptr & ring->ptr_mask;
+	dst = (void *)&ring->ring[occupied];
+	chunk1 = ring->ptr_mask + 1 - occupied;
+	chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
+	chunk2 = count_dw - chunk1;
+	chunk1 <<= 2;
+	chunk2 <<= 2;
+
+	if (chunk1)
+		memcpy(dst, src, chunk1);
+
+	if (chunk2) {
+		src += chunk1;
+		dst = (void *)ring->ring;
+		memcpy(dst, src, chunk2);
+	}
+
+	ring->wptr += count_dw;
+	ring->wptr &= ring->ptr_mask;
+	ring->count_dw -= count_dw;
 }
 
 static inline struct amdgpu_sdma_instance *
-- 
2.12.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC] drm/amd/amdgpu: get rid of else branch
  2017-04-27 16:17 [RFC] drm/amd/amdgpu: get rid of else branch Nikola Pajkovsky
@ 2017-04-28  8:30 ` Christian König
  2017-05-04 12:57   ` Nikola Pajkovsky
  0 siblings, 1 reply; 4+ messages in thread
From: Christian König @ 2017-04-28  8:30 UTC (permalink / raw)
  To: Nikola Pajkovsky, linux-kernel
  Cc: Alex Deucher, David Airlie, dri-devel, Christian König, amd-gfx

Am 27.04.2017 um 18:17 schrieb Nikola Pajkovsky:
> This is super simple elimination of else branch and I should
> probably even use unlikely in
>
>   	if (ring->count_dw < count_dw) {
>
> However, amdgpu_ring_write() has similar if condition, but does not
> return after DRM_ERROR and it looks suspicious. On error, we still
> adding v to ring and keeping count_dw-- below zero.
>
> 	if (ring->count_dw <= 0)
> 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
> 	ring->ring[ring->wptr++] = v;
> 	ring->wptr &= ring->ptr_mask;
> 	ring->count_dw--;
>
> I can obviously be totaly wrong. Hmm?

That's just choosing the lesser evil.

When we write more DW to the ring than expected it is possible (but not 
likely) that we override stuff on the ring buffer which is still 
executed by the command processor leading to a possible CP crash.

But when we completely drop the write the commands in the ring buffer 
will certainly be invalid and so the CP will certainly crash sooner or 
later.

Please add the unlikely() as well and then send out the patch with a 
signed-of-by line and I will be happy to push it into our upstream branch.

Regards,
Christian.

>
> --------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index c1b913541739..c6f4f874ea68 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1596,28 +1596,29 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, void *sr
>   
>   	if (ring->count_dw < count_dw) {
>   		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
> -	} else {
> -		occupied = ring->wptr & ring->ptr_mask;
> -		dst = (void *)&ring->ring[occupied];
> -		chunk1 = ring->ptr_mask + 1 - occupied;
> -		chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
> -		chunk2 = count_dw - chunk1;
> -		chunk1 <<= 2;
> -		chunk2 <<= 2;
> -
> -		if (chunk1)
> -			memcpy(dst, src, chunk1);
> -
> -		if (chunk2) {
> -			src += chunk1;
> -			dst = (void *)ring->ring;
> -			memcpy(dst, src, chunk2);
> -		}
> -
> -		ring->wptr += count_dw;
> -		ring->wptr &= ring->ptr_mask;
> -		ring->count_dw -= count_dw;
> +		return;
>   	}
> +
> +	occupied = ring->wptr & ring->ptr_mask;
> +	dst = (void *)&ring->ring[occupied];
> +	chunk1 = ring->ptr_mask + 1 - occupied;
> +	chunk1 = (chunk1 >= count_dw) ? count_dw: chunk1;
> +	chunk2 = count_dw - chunk1;
> +	chunk1 <<= 2;
> +	chunk2 <<= 2;
> +
> +	if (chunk1)
> +		memcpy(dst, src, chunk1);
> +
> +	if (chunk2) {
> +		src += chunk1;
> +		dst = (void *)ring->ring;
> +		memcpy(dst, src, chunk2);
> +	}
> +
> +	ring->wptr += count_dw;
> +	ring->wptr &= ring->ptr_mask;
> +	ring->count_dw -= count_dw;
>   }
>   
>   static inline struct amdgpu_sdma_instance *

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] drm/amd/amdgpu: get rid of else branch
  2017-04-28  8:30 ` Christian König
@ 2017-05-04 12:57   ` Nikola Pajkovsky
  2017-05-04 13:19     ` Christian König
  0 siblings, 1 reply; 4+ messages in thread
From: Nikola Pajkovsky @ 2017-05-04 12:57 UTC (permalink / raw)
  To: Christian König
  Cc: linux-kernel, Alex Deucher, David Airlie, dri-devel, amd-gfx

Christian König <christian.koenig@amd.com> writes:

> Am 27.04.2017 um 18:17 schrieb Nikola Pajkovsky:
>> This is super simple elimination of else branch and I should
>> probably even use unlikely in
>>
>>   	if (ring->count_dw < count_dw) {
>>
>> However, amdgpu_ring_write() has similar if condition, but does not
>> return after DRM_ERROR and it looks suspicious. On error, we still
>> adding v to ring and keeping count_dw-- below zero.
>>
>> 	if (ring->count_dw <= 0)
>> 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
>> 	ring->ring[ring->wptr++] = v;
>> 	ring->wptr &= ring->ptr_mask;
>> 	ring->count_dw--;
>>
>> I can obviously be totaly wrong. Hmm?
>
> That's just choosing the lesser evil.
>
> When we write more DW to the ring than expected it is possible (but
> not likely) that we override stuff on the ring buffer which is still
> executed by the command processor leading to a possible CP crash.
>
> But when we completely drop the write the commands in the ring buffer
> will certainly be invalid and so the CP will certainly crash sooner or
> later.

Instead of choosing the lesser evil, is there good way to design ring
buffer right way?

> Please add the unlikely() as well and then send out the patch with a
> signed-of-by line and I will be happy to push it into our upstream
> branch.

Proper patch has been sent.

-- 
Nikola

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] drm/amd/amdgpu: get rid of else branch
  2017-05-04 12:57   ` Nikola Pajkovsky
@ 2017-05-04 13:19     ` Christian König
  0 siblings, 0 replies; 4+ messages in thread
From: Christian König @ 2017-05-04 13:19 UTC (permalink / raw)
  To: Nikola Pajkovsky
  Cc: linux-kernel, Alex Deucher, David Airlie, dri-devel, amd-gfx

Am 04.05.2017 um 14:57 schrieb Nikola Pajkovsky:
> Christian König <christian.koenig@amd.com> writes:
>
>> Am 27.04.2017 um 18:17 schrieb Nikola Pajkovsky:
>>> This is super simple elimination of else branch and I should
>>> probably even use unlikely in
>>>
>>>    	if (ring->count_dw < count_dw) {
>>>
>>> However, amdgpu_ring_write() has similar if condition, but does not
>>> return after DRM_ERROR and it looks suspicious. On error, we still
>>> adding v to ring and keeping count_dw-- below zero.
>>>
>>> 	if (ring->count_dw <= 0)
>>> 		DRM_ERROR("amdgpu: writing more dwords to the ring than expected!\n");
>>> 	ring->ring[ring->wptr++] = v;
>>> 	ring->wptr &= ring->ptr_mask;
>>> 	ring->count_dw--;
>>>
>>> I can obviously be totaly wrong. Hmm?
>> That's just choosing the lesser evil.
>>
>> When we write more DW to the ring than expected it is possible (but
>> not likely) that we override stuff on the ring buffer which is still
>> executed by the command processor leading to a possible CP crash.
>>
>> But when we completely drop the write the commands in the ring buffer
>> will certainly be invalid and so the CP will certainly crash sooner or
>> later.
> Instead of choosing the lesser evil, is there good way to design ring
> buffer right way?

It is designed the right way.

See this only happens when a developer increases the number of dw 
written, but forgets to reserve ring buffer space before starting the write.

When the function recognizes that something is wrong it is to late to 
actually reserve more space, so the only option left is printing a 
message for the dev to fix the code.


>> Please add the unlikely() as well and then send out the patch with a
>> signed-of-by line and I will be happy to push it into our upstream
>> branch.
> Proper patch has been sent.

Seen and reviewed, thanks for the help.

Christian.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-05-04 13:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-27 16:17 [RFC] drm/amd/amdgpu: get rid of else branch Nikola Pajkovsky
2017-04-28  8:30 ` Christian König
2017-05-04 12:57   ` Nikola Pajkovsky
2017-05-04 13:19     ` Christian König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).