From aa29688809e41aec4f2fb49bcdd22efd8cc40c61 Mon Sep 17 00:00:00 2001 From: Chaudhary Amit Kumar Date: Thu, 18 Oct 2018 19:12:05 +0530 Subject: [PATCH 1418/4131] drm/amdgpu: Fix CP_HQD_PQ_WPTR initialization on KFD HQD load The return value from copy_from_user() was interpreted as the opposite of its intended meaning. This caused PQ_WPTR to be populated with the uninitialized value from shadow_wptr, causing intermittent HIQ hangs. Always initialize PQ_WPTR to zero if a shadow write pointer is not available. Also check for NULL as this may be mapped in userspace but has a specific meaning when passed to hqd_load(). Change-Id: I3ced7765659a043a53b8123bace0e6288a23b59d Signed-off-by: Jay Cornwall Reviewed-by: David Ogbeide Signed-off-by: Chaudhary Amit Kumar --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 8 ++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 558bf3e..9eca46f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -406,12 +406,13 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, uint32_t page_table_base) { struct amdgpu_device *adev = get_amdgpu_device(kgd); - uint32_t wptr_shadow, is_wptr_shadow_valid; struct cik_mqd *m; + uint32_t wptr_shadow = 0, is_wptr_shadow_valid = 0; m = get_mqd(mqd); - is_wptr_shadow_valid = !get_user(wptr_shadow, wptr); + if (wptr != NULL) + is_wptr_shadow_valid = !get_user(wptr_shadow, wptr); acquire_queue(kgd, pipe_id, queue_id); @@ -458,8 +459,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, WREG32(mmCP_HQD_IQ_RPTR, m->cp_hqd_iq_rptr); - if (is_wptr_shadow_valid) - WREG32(mmCP_HQD_PQ_WPTR, wptr_shadow); + WREG32(mmCP_HQD_PQ_WPTR, (is_wptr_shadow_valid ? wptr_shadow : 0)); WREG32(mmCP_HQD_ACTIVE, m->cp_hqd_active); release_queue(kgd); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 34e4a81..41925d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -322,13 +322,15 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, uint32_t queue_id, uint32_t __user *wptr, uint32_t page_table_base) { - struct vi_mqd *m; - uint32_t shadow_wptr, valid_wptr; struct amdgpu_device *adev = get_amdgpu_device(kgd); + struct vi_mqd *m; + uint32_t wptr_shadow = 0, is_wptr_shadow_valid = 0; m = get_mqd(mqd); - valid_wptr = copy_from_user(&shadow_wptr, wptr, sizeof(shadow_wptr)); + if (wptr != NULL) + is_wptr_shadow_valid = !get_user(wptr_shadow, wptr); + acquire_queue(kgd, pipe_id, queue_id); WREG32(mmCP_MQD_CONTROL, m->cp_mqd_control); @@ -345,10 +347,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR, m->cp_hqd_pq_rptr_report_addr_lo); WREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, m->cp_hqd_pq_rptr_report_addr_hi); - - if (valid_wptr > 0) - WREG32(mmCP_HQD_PQ_WPTR, shadow_wptr); - + WREG32(mmCP_HQD_PQ_WPTR, (is_wptr_shadow_valid ? wptr_shadow : 0)); WREG32(mmCP_HQD_PQ_CONTROL, m->cp_hqd_pq_control); WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, m->cp_hqd_pq_doorbell_control); -- 2.7.4