drm/amdgpu/gfx10: fix issues for suspend/resume
authorJack Xiao <Jack.Xiao@amd.com>
Tue, 16 Apr 2019 09:27:41 +0000 (17:27 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 21 Jun 2019 23:59:27 +0000 (18:59 -0500)
1). use PREEMPT_QUEUE instead of RESET_QUEUE for gfx ring disablement.
2). Need wait for unmapping queue done before continue execution.

Signed-off-by: Jack Xiao <Jack.Xiao@amd.com>
Reviewed-by: Tianci Yin <tianci.yin@amd.com>
Reviewed-by: Xiaojie Yuan <xiaojie.yuan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c

index 274d9087879a4678eabf3100ea8ea3ccbe75d991..22b168d757c9e956878a5b93767edb14f123ea0d 100644 (file)
@@ -3544,8 +3544,9 @@ static int gfx_v10_0_hw_init(void *handle)
 static int gfx10_0_disable_kgq(struct amdgpu_device *adev)
 {
        struct amdgpu_kiq *kiq = &adev->gfx.kiq;
-       struct amdgpu_ring *kiq_ring = &kiq->ring;
-       int i;
+       struct amdgpu_ring *ring, *kiq_ring = &kiq->ring;
+       struct v10_gfx_mqd *mqd;
+       int r, i, j;
 
        if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
                return -EINVAL;
@@ -3554,9 +3555,33 @@ static int gfx10_0_disable_kgq(struct amdgpu_device *adev)
                                        adev->gfx.num_gfx_rings))
                return -ENOMEM;
 
-       for (i = 0; i < adev->gfx.num_gfx_rings; i++)
-               kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.gfx_ring[i],
-                                          RESET_QUEUES, 0, 0);
+       for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
+               ring = &adev->gfx.gfx_ring[i];
+
+               r = amdgpu_bo_reserve(ring->mqd_obj, false);
+               if (unlikely(r != 0))
+                       return r;
+
+               r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
+               if (!r) {
+                       kiq->pmf->kiq_unmap_queues(kiq_ring, ring,
+                                                  PREEMPT_QUEUES, 0, 0);
+                       mqd = ring->mqd_ptr;
+
+                       for (j = 0; j < adev->usec_timeout; j++) {
+                               if (!mqd->cp_gfx_hqd_active)
+                                       break;
+                               udelay(1);
+                       }
+
+                       if (j == adev->usec_timeout)
+                               DRM_ERROR("failed to wait for gfx inactive\n");
+
+                       amdgpu_bo_kunmap(ring->mqd_obj);
+                       ring->mqd_ptr = NULL;
+               }
+               amdgpu_bo_unreserve(ring->mqd_obj);
+       }
 
        return amdgpu_ring_test_ring(kiq_ring);
 }