diff options
author | Jerome Glisse <jglisse@redhat.com> | 2010-03-09 09:45:12 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-05 21:21:11 -0400 |
commit | 90aca4d2740255bd130ea71a91530b9920c70abe (patch) | |
tree | acf9b8a4353e6727cd6cba5b71caaf9f067e465d /drivers/gpu/drm/radeon/r600.c | |
parent | a2d07b7438f015a0349bc9af3c96a8164549bbc5 (diff) |
drm/radeon/kms: simplify & improve GPU reset V2
This simplify and improve GPU reset for R1XX-R6XX hw, it's
not 100% reliable here are result:
- R1XX/R2XX works bunch of time in a row, sometimes it
seems it can work indifinitly
- R3XX/R3XX the most unreliable one, sometimes you will be
able to reset few times, sometimes not even once
- R5XX more reliable than previous hw, seems to work most
of the times but once in a while it fails for no obvious
reasons (same status than previous reset just no same
happy ending)
- R6XX/R7XX are lot more reliable with this patch, still
it seems that it can fail after a bunch (reset every
2sec for 3hour bring down the GPU & computer)
This have been tested on various hw, for some odd reasons
i wasn't able to lockup RS480/RS690 (while they use to
love locking up).
Note that on R1XX-R5XX the cursor will disapear after
lockup haven't checked why, switch to console and back
to X will restore cursor.
Next step is to record the bogus command that leaded to
the lockup.
V2 Fix r6xx resume path to avoid reinitializing blit
module, use the gpu_lockup boolean to avoid entering
inifinite waiting loop on fence while reiniting the GPU
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 53 |
1 files changed, 5 insertions, 48 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 24fd5459fb42..13c9cc34231d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -749,7 +749,6 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
749 | S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) | | 749 | S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) | |
750 | S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) | | 750 | S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) | |
751 | S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1); | 751 | S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1); |
752 | u32 srbm_reset = 0; | ||
753 | u32 tmp; | 752 | u32 tmp; |
754 | 753 | ||
755 | dev_info(rdev->dev, "GPU softreset \n"); | 754 | dev_info(rdev->dev, "GPU softreset \n"); |
@@ -764,7 +763,7 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
764 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 763 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
765 | } | 764 | } |
766 | /* Disable CP parsing/prefetching */ | 765 | /* Disable CP parsing/prefetching */ |
767 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(0xff)); | 766 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); |
768 | /* Check if any of the rendering block is busy and reset it */ | 767 | /* Check if any of the rendering block is busy and reset it */ |
769 | if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) || | 768 | if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) || |
770 | (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) { | 769 | (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) { |
@@ -783,55 +782,17 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
783 | S_008020_SOFT_RESET_VGT(1); | 782 | S_008020_SOFT_RESET_VGT(1); |
784 | dev_info(rdev->dev, " R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); | 783 | dev_info(rdev->dev, " R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); |
785 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | 784 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); |
786 | (void)RREG32(R_008020_GRBM_SOFT_RESET); | 785 | RREG32(R_008020_GRBM_SOFT_RESET); |
787 | mdelay(1); | 786 | mdelay(15); |
788 | WREG32(R_008020_GRBM_SOFT_RESET, 0); | 787 | WREG32(R_008020_GRBM_SOFT_RESET, 0); |
789 | (void)RREG32(R_008020_GRBM_SOFT_RESET); | ||
790 | } | 788 | } |
791 | /* Reset CP (we always reset CP) */ | 789 | /* Reset CP (we always reset CP) */ |
792 | tmp = S_008020_SOFT_RESET_CP(1); | 790 | tmp = S_008020_SOFT_RESET_CP(1); |
793 | dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); | 791 | dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); |
794 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | 792 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); |
795 | (void)RREG32(R_008020_GRBM_SOFT_RESET); | 793 | RREG32(R_008020_GRBM_SOFT_RESET); |
796 | udelay(50); | 794 | mdelay(15); |
797 | WREG32(R_008020_GRBM_SOFT_RESET, 0); | 795 | WREG32(R_008020_GRBM_SOFT_RESET, 0); |
798 | (void)RREG32(R_008020_GRBM_SOFT_RESET); | ||
799 | /* Reset others GPU block if necessary */ | ||
800 | if (G_000E50_RLC_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
801 | srbm_reset |= S_000E60_SOFT_RESET_RLC(1); | ||
802 | if (G_000E50_GRBM_RQ_PENDING(RREG32(R_000E50_SRBM_STATUS))) | ||
803 | srbm_reset |= S_000E60_SOFT_RESET_GRBM(1); | ||
804 | if (G_000E50_HI_RQ_PENDING(RREG32(R_000E50_SRBM_STATUS))) | ||
805 | srbm_reset |= S_000E60_SOFT_RESET_IH(1); | ||
806 | if (G_000E50_VMC_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
807 | srbm_reset |= S_000E60_SOFT_RESET_VMC(1); | ||
808 | if (G_000E50_MCB_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
809 | srbm_reset |= S_000E60_SOFT_RESET_MC(1); | ||
810 | if (G_000E50_MCDZ_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
811 | srbm_reset |= S_000E60_SOFT_RESET_MC(1); | ||
812 | if (G_000E50_MCDY_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
813 | srbm_reset |= S_000E60_SOFT_RESET_MC(1); | ||
814 | if (G_000E50_MCDX_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
815 | srbm_reset |= S_000E60_SOFT_RESET_MC(1); | ||
816 | if (G_000E50_MCDW_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
817 | srbm_reset |= S_000E60_SOFT_RESET_MC(1); | ||
818 | if (G_000E50_RLC_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
819 | srbm_reset |= S_000E60_SOFT_RESET_RLC(1); | ||
820 | if (G_000E50_SEM_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
821 | srbm_reset |= S_000E60_SOFT_RESET_SEM(1); | ||
822 | if (G_000E50_BIF_BUSY(RREG32(R_000E50_SRBM_STATUS))) | ||
823 | srbm_reset |= S_000E60_SOFT_RESET_BIF(1); | ||
824 | dev_info(rdev->dev, " R_000E60_SRBM_SOFT_RESET=0x%08X\n", srbm_reset); | ||
825 | WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset); | ||
826 | (void)RREG32(R_000E60_SRBM_SOFT_RESET); | ||
827 | mdelay(1); | ||
828 | WREG32(R_000E60_SRBM_SOFT_RESET, 0); | ||
829 | (void)RREG32(R_000E60_SRBM_SOFT_RESET); | ||
830 | WREG32(R_000E60_SRBM_SOFT_RESET, srbm_reset); | ||
831 | (void)RREG32(R_000E60_SRBM_SOFT_RESET); | ||
832 | mdelay(1); | ||
833 | WREG32(R_000E60_SRBM_SOFT_RESET, 0); | ||
834 | (void)RREG32(R_000E60_SRBM_SOFT_RESET); | ||
835 | /* Wait a little for things to settle down */ | 796 | /* Wait a little for things to settle down */ |
836 | mdelay(1); | 797 | mdelay(1); |
837 | dev_info(rdev->dev, " R_008010_GRBM_STATUS=0x%08X\n", | 798 | dev_info(rdev->dev, " R_008010_GRBM_STATUS=0x%08X\n", |
@@ -840,10 +801,6 @@ int r600_gpu_soft_reset(struct radeon_device *rdev) | |||
840 | RREG32(R_008014_GRBM_STATUS2)); | 801 | RREG32(R_008014_GRBM_STATUS2)); |
841 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", | 802 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS=0x%08X\n", |
842 | RREG32(R_000E50_SRBM_STATUS)); | 803 | RREG32(R_000E50_SRBM_STATUS)); |
843 | /* After reset we need to reinit the asic as GPU often endup in an | ||
844 | * incoherent state. | ||
845 | */ | ||
846 | atom_asic_init(rdev->mode_info.atom_context); | ||
847 | rv515_mc_resume(rdev, &save); | 804 | rv515_mc_resume(rdev, &save); |
848 | return 0; | 805 | return 0; |
849 | } | 806 | } |