diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3350-drm-amdkfd-Fix-kernel-queue-wrapping-bugs.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3350-drm-amdkfd-Fix-kernel-queue-wrapping-bugs.patch | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3350-drm-amdkfd-Fix-kernel-queue-wrapping-bugs.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3350-drm-amdkfd-Fix-kernel-queue-wrapping-bugs.patch new file mode 100644 index 00000000..a0664365 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3350-drm-amdkfd-Fix-kernel-queue-wrapping-bugs.patch @@ -0,0 +1,67 @@ +From 6c7cd6dc01a7ac5c68de98385bd12f76172101be Mon Sep 17 00:00:00 2001 +From: Yong Zhao <yong.zhao@amd.com> +Date: Wed, 20 Sep 2017 18:10:21 -0400 +Subject: [PATCH 3350/4131] drm/amdkfd: Fix kernel-queue wrapping bugs + +Avoid intermediate negative numbers when doing calculations with a mix +of signed and unsigned variables where implicit conversions can lead +to unexpected results. + +When kernel queue buffer wraps around to 0, we need to check that rptr +won't be overwritten by the new packet. + +Signed-off-by: Yong Zhao <yong.zhao@amd.com> +Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com> +Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com> +--- + drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +index d7ed10e..8b0c064 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +@@ -210,6 +210,11 @@ static int acquire_packet_buffer(struct kernel_queue *kq, + uint32_t wptr, rptr; + unsigned int *queue_address; + ++ /* When rptr == wptr, the buffer is empty. ++ * When rptr == wptr + 1, the buffer is full. ++ * It is always rptr that advances to the position of wptr, rather than ++ * the opposite. So we can only use up to queue_size_dwords - 1 dwords. ++ */ + rptr = *kq->rptr_kernel; + wptr = *kq->wptr_kernel; + queue_address = (unsigned int *)kq->pq_kernel_addr; +@@ -219,11 +224,10 @@ static int acquire_packet_buffer(struct kernel_queue *kq, + pr_debug("wptr: %d\n", wptr); + pr_debug("queue_address 0x%p\n", queue_address); + +- available_size = (rptr - 1 - wptr + queue_size_dwords) % ++ available_size = (rptr + queue_size_dwords - 1 - wptr) % + queue_size_dwords; + +- if (packet_size_in_dwords >= queue_size_dwords || +- packet_size_in_dwords >= available_size) { ++ if (packet_size_in_dwords > available_size) { + /* + * make sure calling functions know + * acquire_packet_buffer() failed +@@ -233,6 +237,14 @@ static int acquire_packet_buffer(struct kernel_queue *kq, + } + + if (wptr + packet_size_in_dwords >= queue_size_dwords) { ++ /* make sure after rolling back to position 0, there is ++ * still enough space. ++ */ ++ if (packet_size_in_dwords >= rptr) { ++ *buffer_ptr = NULL; ++ return -ENOMEM; ++ } ++ /* fill nops, roll back and start at position 0 */ + while (wptr > 0) { + queue_address[wptr] = kq->nop_packet; + wptr = (wptr + 1) % queue_size_dwords; +-- +2.7.4 + |