aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r300.c
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2010-03-09 09:45:12 -0500
committerDave Airlie <airlied@redhat.com>2010-04-05 21:21:11 -0400
commit90aca4d2740255bd130ea71a91530b9920c70abe (patch)
treeacf9b8a4353e6727cd6cba5b71caaf9f067e465d /drivers/gpu/drm/radeon/r300.c
parenta2d07b7438f015a0349bc9af3c96a8164549bbc5 (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/r300.c')
-rw-r--r--drivers/gpu/drm/radeon/r300.c134
1 files changed, 59 insertions, 75 deletions
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 7d5de5dbde23..199110ef8df2 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -151,6 +151,10 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
151 u32 tmp; 151 u32 tmp;
152 int r; 152 int r;
153 153
154 WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
155 WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
156 WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
157 WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
154 tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); 158 tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
155 tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; 159 tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
156 WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); 160 WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
@@ -323,7 +327,6 @@ void r300_gpu_init(struct radeon_device *rdev)
323{ 327{
324 uint32_t gb_tile_config, tmp; 328 uint32_t gb_tile_config, tmp;
325 329
326 r100_hdp_reset(rdev);
327 /* FIXME: rv380 one pipes ? */ 330 /* FIXME: rv380 one pipes ? */
328 if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || 331 if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
329 (rdev->family == CHIP_R350)) { 332 (rdev->family == CHIP_R350)) {
@@ -376,57 +379,6 @@ void r300_gpu_init(struct radeon_device *rdev)
376 rdev->num_gb_pipes, rdev->num_z_pipes); 379 rdev->num_gb_pipes, rdev->num_z_pipes);
377} 380}
378 381
379int r300_ga_reset(struct radeon_device *rdev)
380{
381 uint32_t tmp;
382 bool reinit_cp;
383 int i;
384
385 reinit_cp = rdev->cp.ready;
386 rdev->cp.ready = false;
387 for (i = 0; i < rdev->usec_timeout; i++) {
388 WREG32(RADEON_CP_CSQ_MODE, 0);
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 }
413 for (i = 0; i < rdev->usec_timeout; i++) {
414 tmp = RREG32(RADEON_RBBM_STATUS);
415 if (!(tmp & ((1 << 20) | (1 << 26)))) {
416 DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
417 tmp);
418 if (reinit_cp) {
419 return r100_cp_init(rdev, rdev->cp.ring_size);
420 }
421 return 0;
422 }
423 DRM_UDELAY(1);
424 }
425 tmp = RREG32(RADEON_RBBM_STATUS);
426 DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
427 return -1;
428}
429
430bool r300_gpu_is_lockup(struct radeon_device *rdev) 382bool r300_gpu_is_lockup(struct radeon_device *rdev)
431{ 383{
432 u32 rbbm_status; 384 u32 rbbm_status;
@@ -451,37 +403,69 @@ bool r300_gpu_is_lockup(struct radeon_device *rdev)
451 403
452int r300_asic_reset(struct radeon_device *rdev) 404int r300_asic_reset(struct radeon_device *rdev)
453{ 405{
454 uint32_t status; 406 struct r100_mc_save save;
407 u32 status, tmp;
455 408
456 /* reset order likely matter */ 409 r100_mc_stop(rdev, &save);
457 status = RREG32(RADEON_RBBM_STATUS); 410 status = RREG32(R_000E40_RBBM_STATUS);
458 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 411 if (!G_000E40_GUI_ACTIVE(status)) {
459 /* reset HDP */ 412 return 0;
460 r100_hdp_reset(rdev);
461 /* reset rb2d */
462 if (status & ((1 << 17) | (1 << 18) | (1 << 27))) {
463 r100_rb2d_reset(rdev);
464 }
465 /* reset GA */
466 if (status & ((1 << 20) | (1 << 26))) {
467 r300_ga_reset(rdev);
468 }
469 /* reset CP */
470 status = RREG32(RADEON_RBBM_STATUS);
471 if (status & (1 << 16)) {
472 r100_cp_reset(rdev);
473 } 413 }
414 status = RREG32(R_000E40_RBBM_STATUS);
415 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
416 /* stop CP */
417 WREG32(RADEON_CP_CSQ_CNTL, 0);
418 tmp = RREG32(RADEON_CP_RB_CNTL);
419 WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
420 WREG32(RADEON_CP_RB_RPTR_WR, 0);
421 WREG32(RADEON_CP_RB_WPTR, 0);
422 WREG32(RADEON_CP_RB_CNTL, tmp);
423 /* save PCI state */
424 pci_save_state(rdev->pdev);
425 /* disable bus mastering */
426 r100_bm_disable(rdev);
427 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
428 S_0000F0_SOFT_RESET_GA(1));
429 RREG32(R_0000F0_RBBM_SOFT_RESET);
430 mdelay(500);
431 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
432 mdelay(1);
433 status = RREG32(R_000E40_RBBM_STATUS);
434 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
435 /* resetting the CP seems to be problematic sometimes it end up
436 * hard locking the computer, but it's necessary for successfull
437 * reset more test & playing is needed on R3XX/R4XX to find a
438 * reliable (if any solution)
439 */
440 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
441 RREG32(R_0000F0_RBBM_SOFT_RESET);
442 mdelay(500);
443 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
444 mdelay(1);
445 status = RREG32(R_000E40_RBBM_STATUS);
446 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
447 /* reset MC */
448 WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_MC(1));
449 RREG32(R_0000F0_RBBM_SOFT_RESET);
450 mdelay(500);
451 WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
452 mdelay(1);
453 status = RREG32(R_000E40_RBBM_STATUS);
454 dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
455 /* restore PCI & busmastering */
456 pci_restore_state(rdev->pdev);
457 r100_enable_bm(rdev);
474 /* Check if GPU is idle */ 458 /* Check if GPU is idle */
475 status = RREG32(RADEON_RBBM_STATUS); 459 if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
476 if (status & RADEON_RBBM_ACTIVE) { 460 dev_err(rdev->dev, "failed to reset GPU\n");
477 DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); 461 rdev->gpu_lockup = true;
478 return -1; 462 return -1;
479 } 463 }
480 DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); 464 r100_mc_resume(rdev, &save);
465 dev_info(rdev->dev, "GPU reset succeed\n");
481 return 0; 466 return 0;
482} 467}
483 468
484
485/* 469/*
486 * r300,r350,rv350,rv380 VRAM info 470 * r300,r350,rv350,rv380 VRAM info
487 */ 471 */