aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r300.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-04-19 23:15:05 -0400
committerDave Airlie <airlied@redhat.com>2010-04-19 23:15:05 -0400
commit0bcb1d844ac638a4c4280f697d5bfac9791e9a70 (patch)
treec51aa8427a81cb64dded4d4f68bf1a1b8ad32041 /drivers/gpu/drm/radeon/r300.c
parentc9c2625ff4fc4ce652e686f895059d2902c01ca0 (diff)
parent90aca4d2740255bd130ea71a91530b9920c70abe (diff)
Merge branch 'drm-radeon-lockup' into drm-core-next
* drm-radeon-lockup: drm/radeon/kms: simplify & improve GPU reset V2 drm/radeon/kms: rename gpu_reset to asic_reset drm/radeon/kms: fence cleanup + more reliable GPU lockup detection V4 Conflicts: drivers/gpu/drm/radeon/r300.c
Diffstat (limited to 'drivers/gpu/drm/radeon/r300.c')
-rw-r--r--drivers/gpu/drm/radeon/r300.c156
1 files changed, 82 insertions, 74 deletions
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index bd75f99bd65e..bb005bff4b08 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -27,8 +27,9 @@
27 */ 27 */
28#include <linux/seq_file.h> 28#include <linux/seq_file.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include "drmP.h" 30#include <drm/drmP.h>
31#include "drm.h" 31#include <drm/drm.h>
32#include <drm/drm_crtc_helper.h>
32#include "radeon_reg.h" 33#include "radeon_reg.h"
33#include "radeon.h" 34#include "radeon.h"
34#include "radeon_asic.h" 35#include "radeon_asic.h"
@@ -151,6 +152,10 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
151 u32 tmp; 152 u32 tmp;
152 int r; 153 int r;
153 154
155 WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
156 WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
157 WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
158 WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
154 tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 159 tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
155 tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 160 tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
156 WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); 161 WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
@@ -323,7 +328,6 @@ void r300_gpu_init(struct radeon_device *rdev)
323{ 328{
324 uint32_t gb_tile_config, tmp; 329 uint32_t gb_tile_config, tmp;
325 330
326 r100_hdp_reset(rdev);
327 /* FIXME: rv380 one pipes ? */ 331 /* FIXME: rv380 one pipes ? */
328 if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || 332 if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
329 (rdev->family == CHIP_R350)) { 333 (rdev->family == CHIP_R350)) {
@@ -376,89 +380,93 @@ void r300_gpu_init(struct radeon_device *rdev)
376 rdev->num_gb_pipes, rdev->num_z_pipes); 380 rdev->num_gb_pipes, rdev->num_z_pipes);
377} 381}
378 382
379int r300_ga_reset(struct radeon_device *rdev) 383bool r300_gpu_is_lockup(struct radeon_device *rdev)
380{ 384{
381 uint32_t tmp; 385 u32 rbbm_status;
382 bool reinit_cp; 386 int r;
383 int i;
384 387
385 reinit_cp = rdev->cp.ready; 388 rbbm_status = RREG32(R_000E40_RBBM_STATUS);
386 rdev->cp.ready = false; 389 if (!G_000E40_GUI_ACTIVE(rbbm_status)) {
387 for (i = 0; i < rdev->usec_timeout; i++) { 390 r100_gpu_lockup_update(&rdev->config.r300.lockup, &rdev->cp);
388 WREG32(RADEON_CP_CSQ_MODE, 0); 391 return false;
389 WREG32(RADEON_CP_CSQ_CNTL, 0);
390 WREG32(RADEON_RBBM_SOFT_RESET, 0x32005);
391 (void)RREG32(RADEON_RBBM_SOFT_RESET);
392 udelay(200);
393 WREG32(RADEON_RBBM_SOFT_RESET, 0);
394 /* Wait to prevent race in RBBM_STATUS */
395 mdelay(1);
396 tmp = RREG32(RADEON_RBBM_STATUS);
397 if (tmp & ((1 << 20) | (1 << 26))) {
398 DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)", tmp);
399 /* GA still busy soft reset it */
400 WREG32(0x429C, 0x200);
401 WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
402 WREG32(R300_RE_SCISSORS_TL, 0);
403 WREG32(R300_RE_SCISSORS_BR, 0);
404 WREG32(0x24AC, 0);
405 }
406 /* Wait to prevent race in RBBM_STATUS */
407 mdelay(1);
408 tmp = RREG32(RADEON_RBBM_STATUS);
409 if (!(tmp & ((1 << 20) | (1 << 26)))) {
410 break;
411 }
412 } 392 }
413 for (i = 0; i < rdev->usec_timeout; i++) { 393 /* force CP activities */
414 tmp = RREG32(RADEON_RBBM_STATUS); 394 r = radeon_ring_lock(rdev, 2);
415 if (!(tmp & ((1 << 20) | (1 << 26)))) { 395 if (!r) {
416 DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n", 396 /* PACKET2 NOP */
417 tmp); 397 radeon_ring_write(rdev, 0x80000000);
418 if (reinit_cp) { 398 radeon_ring_write(rdev, 0x80000000);
419 return r100_cp_init(rdev, rdev->cp.ring_size); 399 radeon_ring_unlock_commit(rdev);
420 }
421 return 0;
422 }
423 DRM_UDELAY(1);
424 } 400 }
425 tmp = RREG32(RADEON_RBBM_STATUS); 401 rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
426 DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp); 402 return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, &rdev->cp);
427 return -1;
428} 403}
429 404
430int r300_gpu_reset(struct radeon_device *rdev) 405int r300_asic_reset(struct radeon_device *rdev)
431{ 406{
432 uint32_t status; 407 struct r100_mc_save save;
433 408 u32 status, tmp;
434 /* reset order likely matter */ 409
435 status = RREG32(RADEON_RBBM_STATUS); 410 r100_mc_stop(rdev, &save);
436 /* reset HDP */ 411 status = RREG32(R_000E40_RBBM_STATUS);
437 r100_hdp_reset(rdev); 412 if (!G_000E40_GUI_ACTIVE(status)) {
438 /* reset rb2d */ 413 return 0;
439 if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
440 r100_rb2d_reset(rdev);
441 }
442 /* reset GA */
443 if (status & ((1 << 20) | (1 << 26))) {
444 r300_ga_reset(rdev);
445 }
446 /* reset CP */
447 status = RREG32(RADEON_RBBM_STATUS);
448 if (status & (1 << 16)) {
449 r100_cp_reset(rdev);
450 } 414 }
415 status = RREG32(R_000E40_RBBM_STATUS);
416 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
417 /* stop CP */
418 WREG32(RADEON_CP_CSQ_CNTL, 0);
419 tmp = RREG32(RADEON_CP_RB_CNTL);
420 WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
421 WREG32(RADEON_CP_RB_RPTR_WR, 0);
422 WREG32(RADEON_CP_RB_WPTR, 0);
423 WREG32(RADEON_CP_RB_CNTL, tmp);
424 /* save PCI state */
425 pci_save_state(rdev->pdev);
426 /* disable bus mastering */
427 r100_bm_disable(rdev);
428 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
429 S_0000F0_SOFT_RESET_GA(1));
430 RREG32(R_0000F0_RBBM_SOFT_RESET);
431 mdelay(500);
432 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
433 mdelay(1);
434 status = RREG32(R_000E40_RBBM_STATUS);
435 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
436 /* resetting the CP seems to be problematic sometimes it end up
437 * hard locking the computer, but it's necessary for successfull
438 * reset more test & playing is needed on R3XX/R4XX to find a
439 * reliable (if any solution)
440 */
441 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
442 RREG32(R_0000F0_RBBM_SOFT_RESET);
443 mdelay(500);
444 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
445 mdelay(1);
446 status = RREG32(R_000E40_RBBM_STATUS);
447 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
448 /* reset MC */
449 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1));
450 RREG32(R_0000F0_RBBM_SOFT_RESET);
451 mdelay(500);
452 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
453 mdelay(1);
454 status = RREG32(R_000E40_RBBM_STATUS);
455 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
456 /* restore PCI & busmastering */
457 pci_restore_state(rdev->pdev);
458 r100_enable_bm(rdev);
451 /* Check if GPU is idle */ 459 /* Check if GPU is idle */
452 status = RREG32(RADEON_RBBM_STATUS); 460 if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
453 if (status & RADEON_RBBM_ACTIVE) { 461 dev_err(rdev->dev, "failed to reset GPU\n");
454 DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 462 rdev->gpu_lockup = true;
455 return -1; 463 return -1;
456 } 464 }
457 DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 465 r100_mc_resume(rdev, &save);
466 dev_info(rdev->dev, "GPU reset succeed\n");
458 return 0; 467 return 0;
459} 468}
460 469
461
462/* 470/*
463 * r300,r350,rv350,rv380 VRAM info 471 * r300,r350,rv350,rv380 VRAM info
464 */ 472 */
@@ -1317,7 +1325,7 @@ int r300_resume(struct radeon_device *rdev)
1317 /* Resume clock before doing reset */ 1325 /* Resume clock before doing reset */
1318 r300_clock_startup(rdev); 1326 r300_clock_startup(rdev);
1319 /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 1327 /* Reset gpu before posting otherwise ATOM will enter infinite loop */
1320 if (radeon_gpu_reset(rdev)) { 1328 if (radeon_asic_reset(rdev)) {
1321 dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 1329 dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1322 RREG32(R_000E40_RBBM_STATUS), 1330 RREG32(R_000E40_RBBM_STATUS),
1323 RREG32(R_0007C0_CP_STAT)); 1331 RREG32(R_0007C0_CP_STAT));
@@ -1388,7 +1396,7 @@ int r300_init(struct radeon_device *rdev)
1388 return r; 1396 return r;
1389 } 1397 }
1390 /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 1398 /* Reset gpu before posting otherwise ATOM will enter infinite loop */
1391 if (radeon_gpu_reset(rdev)) { 1399 if (radeon_asic_reset(rdev)) {
1392 dev_warn(rdev->dev, 1400 dev_warn(rdev->dev,
1393 "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 1401 "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1394 RREG32(R_000E40_RBBM_STATUS), 1402 RREG32(R_000E40_RBBM_STATUS),