drm/radeon/kms: check/restore sanity before doing anything else with GPU.
authorDave Airlie <airlied@redhat.com>
Thu, 15 Jul 2010 02:13:50 +0000 (12:13 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 2 Aug 2010 00:00:09 +0000 (10:00 +1000)
On systems using kexec, the new kernel is booted straight from the old kernel, without any warning to the graphics driver. So the GPU is basically left as-is in a running state, however the CPU side is completly reset.

Without stating the saneness of anyone using kexec on live systems, we should at least try not to crash the GPU. This patch resets 3 registers to 0 that could cause bad things to happen to the running system.

This allows kexec to work on a Power6/RN50 system.

Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rv515.c

index 5aa2995273178509b4ad505769c65c0bf746220c..5d14732dc28492b9ecc56baf39285e97aa9e25dd 100644 (file)
@@ -3809,6 +3809,31 @@ void r100_fini(struct radeon_device *rdev)
        rdev->bios = NULL;
 }
 
+/*
+ * Due to how kexec works, it can leave the hw fully initialised when it
+ * boots the new kernel. However doing our init sequence with the CP and
+ * WB stuff setup causes GPU hangs on the RN50 at least. So at startup
+ * do some quick sanity checks and restore sane values to avoid this
+ * problem.
+ */
+void r100_restore_sanity(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG32(RADEON_CP_CSQ_CNTL);
+       if (tmp) {
+               WREG32(RADEON_CP_CSQ_CNTL, 0);
+       }
+       tmp = RREG32(RADEON_CP_RB_CNTL);
+       if (tmp) {
+               WREG32(RADEON_CP_RB_CNTL, 0);
+       }
+       tmp = RREG32(RADEON_SCRATCH_UMSK);
+       if (tmp) {
+               WREG32(RADEON_SCRATCH_UMSK, 0);
+       }
+}
+
 int r100_init(struct radeon_device *rdev)
 {
        int r;
@@ -3821,6 +3846,8 @@ int r100_init(struct radeon_device *rdev)
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* sanity check some register to avoid hangs like after kexec */
+       r100_restore_sanity(rdev);
        /* TODO: disable VGA need to use VGA request */
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
index 7e81db5eb8041b1c66afe1ade046724abf235805..3c34da0c899a7600d2309aeb3d9da8f858e94e08 100644 (file)
@@ -1377,6 +1377,8 @@ int r300_init(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
        /* TODO: disable VGA need to use VGA request */
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
                if (ASIC_IS_AVIVO(rdev))
index e6c89142bb4d24323920636cf0e2499c5e17cf59..59f7bccc5be0a291dcf0fcfb9487080ea93d5693 100644 (file)
@@ -343,6 +343,8 @@ int r420_init(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
        /* TODO: disable VGA need to use VGA request */
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
                if (ASIC_IS_AVIVO(rdev))
index 34330df2848329c178a9f2a659d44b0596b0bbaf..213e2e0027a3b63f5364a4570b105940d1fe52c9 100644 (file)
@@ -230,6 +230,8 @@ int r520_init(struct radeon_device *rdev)
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* TODO: disable VGA need to use VGA request */
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
index c0bbaa64157a466efb81990431903dc8fbe2dc33..a5aff755f0d2e185dbdd4a1efd541dea5dae78fa 100644 (file)
@@ -113,6 +113,7 @@ void r100_wb_fini(struct radeon_device *rdev);
 int r100_wb_init(struct radeon_device *rdev);
 int r100_cp_reset(struct radeon_device *rdev);
 void r100_vga_render_disable(struct radeon_device *rdev);
+void r100_restore_sanity(struct radeon_device *rdev);
 int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
                                         struct radeon_cs_packet *pkt,
                                         struct radeon_bo *robj);
index 9e4240b3bf0bb1ff950b4c74a8e003fc51903e2b..c178481101e9506a2792bd5ca638fda3be59b5e6 100644 (file)
@@ -480,6 +480,8 @@ int rs400_init(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
        /* TODO: disable VGA need to use VGA request */
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
                if (ASIC_IS_AVIVO(rdev))
index 27d2e706c650258a3c3aeec76dde828ea500b7d0..c5760921d1668db6cc4e64911543fa57c5fdcbe1 100644 (file)
@@ -879,6 +879,8 @@ int rs600_init(struct radeon_device *rdev)
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* BIOS */
        if (!radeon_get_bios(rdev)) {
                if (ASIC_IS_AVIVO(rdev))
index 23676b659e65488260679c8375d8042d8f38e19e..3dde54d57d0916d1571821ee8d3c61e6eab213c9 100644 (file)
@@ -707,6 +707,8 @@ int rs690_init(struct radeon_device *rdev)
        radeon_scratch_init(rdev);
        /* Initialize surface registers */
        radeon_surface_init(rdev);
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* TODO: disable VGA need to use VGA request */
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
index 7d9a7b0a180ac7b735702221450e2a9e12be92fe..3f04f735deae802be3af6d0d531caaac945b5323 100644 (file)
@@ -468,6 +468,8 @@ int rv515_init(struct radeon_device *rdev)
        /* Initialize surface registers */
        radeon_surface_init(rdev);
        /* TODO: disable VGA need to use VGA request */
+       /* restore some register to sane defaults */
+       r100_restore_sanity(rdev);
        /* BIOS*/
        if (!radeon_get_bios(rdev)) {
                if (ASIC_IS_AVIVO(rdev))