drm/amdgpu: Halt rlc/cp in rlc_safe_mode
authorRex Zhu <Rex.Zhu@amd.com>
Tue, 11 Sep 2018 02:33:38 +0000 (10:33 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Sep 2018 02:09:19 +0000 (21:09 -0500)
before halt rlc/cp, need to
1. enter rlc safe mode
2. wait rlc/cp idle

Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Hang Zhou <hang.zhou@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c

index 05b5bba7a5831e2fd4d3bc532a8f9ad3abce7d01..93d7fe5c94dc9630d8356f12437b856be16066c4 100644 (file)
@@ -5080,6 +5080,55 @@ static int gfx_v8_0_kcq_disable(struct amdgpu_device *adev)
        return r;
 }
 
+static bool gfx_v8_0_is_idle(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (REG_GET_FIELD(RREG32(mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)
+               || RREG32(mmGRBM_STATUS2) != 0x8)
+               return false;
+       else
+               return true;
+}
+
+static bool gfx_v8_0_rlc_is_idle(void *handle)
+{
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (RREG32(mmGRBM_STATUS2) != 0x8)
+               return false;
+       else
+               return true;
+}
+
+static int gfx_v8_0_wait_for_rlc_idle(void *handle)
+{
+       unsigned int i;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       for (i = 0; i < adev->usec_timeout; i++) {
+               if (gfx_v8_0_rlc_is_idle(handle))
+                       return 0;
+
+               udelay(1);
+       }
+       return -ETIMEDOUT;
+}
+
+static int gfx_v8_0_wait_for_idle(void *handle)
+{
+       unsigned int i;
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       for (i = 0; i < adev->usec_timeout; i++) {
+               if (gfx_v8_0_is_idle(handle))
+                       return 0;
+
+               udelay(1);
+       }
+       return -ETIMEDOUT;
+}
+
 static int gfx_v8_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -5098,9 +5147,16 @@ static int gfx_v8_0_hw_fini(void *handle)
                pr_debug("For SRIOV client, shouldn't do anything.\n");
                return 0;
        }
-       gfx_v8_0_cp_enable(adev, false);
-       gfx_v8_0_rlc_stop(adev);
-
+       adev->gfx.rlc.funcs->enter_safe_mode(adev);
+       if (!gfx_v8_0_wait_for_idle(adev))
+               gfx_v8_0_cp_enable(adev, false);
+       else
+               pr_err("cp is busy, skip halt cp\n");
+       if (!gfx_v8_0_wait_for_rlc_idle(adev))
+               gfx_v8_0_rlc_stop(adev);
+       else
+               pr_err("rlc is busy, skip halt rlc\n");
+       adev->gfx.rlc.funcs->exit_safe_mode(adev);
        return 0;
 }
 
@@ -5121,30 +5177,6 @@ static int gfx_v8_0_resume(void *handle)
        return r;
 }
 
-static bool gfx_v8_0_is_idle(void *handle)
-{
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       if (REG_GET_FIELD(RREG32(mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE))
-               return false;
-       else
-               return true;
-}
-
-static int gfx_v8_0_wait_for_idle(void *handle)
-{
-       unsigned i;
-       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-       for (i = 0; i < adev->usec_timeout; i++) {
-               if (gfx_v8_0_is_idle(handle))
-                       return 0;
-
-               udelay(1);
-       }
-       return -ETIMEDOUT;
-}
-
 static bool gfx_v8_0_check_soft_reset(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;