drm/radeon: add a bios scratch asic hung helper
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 18 Jan 2013 18:05:39 +0000 (13:05 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 31 Jan 2013 21:24:49 +0000 (16:24 -0500)
Used by all asic families from r600+.
Flag for the vbios and later instances of the driver
that the GPU is hung.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/si.c

index a1e12bf..dd1d188 100644 (file)
@@ -2433,6 +2433,8 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
+       r600_set_bios_scratch_engine_hung(rdev, true);
+
        evergreen_mc_stop(rdev, &save);
        if (evergreen_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
@@ -2448,6 +2450,9 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        udelay(50);
 
        evergreen_mc_resume(rdev, &save);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
+
        return 0;
 }
 
index 835992d..af9e86d 100644 (file)
@@ -1422,6 +1422,8 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        if (reset_mask == 0)
                return 0;
 
+       r600_set_bios_scratch_engine_hung(rdev, true);
+
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
        dev_info(rdev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_ADDR   0x%08X\n",
@@ -1448,6 +1450,9 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        udelay(50);
 
        evergreen_mc_resume(rdev, &save);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
+
        return 0;
 }
 
index becb03e..a620817 100644 (file)
@@ -1254,6 +1254,18 @@ void r600_vram_scratch_fini(struct radeon_device *rdev)
        radeon_bo_unref(&rdev->vram_scratch.robj);
 }
 
+void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung)
+{
+       u32 tmp = RREG32(R600_BIOS_3_SCRATCH);
+
+       if (hung)
+               tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+       else
+               tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+
+       WREG32(R600_BIOS_3_SCRATCH, tmp);
+}
+
 /* We doesn't check that the GPU really needs a reset we simply do the
  * reset, it's up to the caller to determine if the GPU needs one. We
  * might add an helper function to check that.
@@ -1389,6 +1401,8 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
 
        dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask);
 
+       r600_set_bios_scratch_engine_hung(rdev, true);
+
        rv515_mc_stop(rdev, &save);
        if (r600_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
@@ -1404,6 +1418,9 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        mdelay(1);
 
        rv515_mc_resume(rdev, &save);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
+
        return 0;
 }
 
index ec3b739..6539d6c 100644 (file)
@@ -1860,6 +1860,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
 /* Common functions */
 /* AGP */
 extern int radeon_gpu_reset(struct radeon_device *rdev);
+extern void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung);
 extern void radeon_agp_disable(struct radeon_device *rdev);
 extern int radeon_modeset_init(struct radeon_device *rdev);
 extern void radeon_modeset_fini(struct radeon_device *rdev);
index f06072f..1fc0e55 100644 (file)
@@ -2231,6 +2231,8 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
                 RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
 
+       r600_set_bios_scratch_engine_hung(rdev, true);
+
        evergreen_mc_stop(rdev, &save);
        if (radeon_mc_wait_for_idle(rdev)) {
                dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
@@ -2246,6 +2248,9 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask)
        udelay(50);
 
        evergreen_mc_resume(rdev, &save);
+
+       r600_set_bios_scratch_engine_hung(rdev, false);
+
        return 0;
 }