diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 164 |
1 files changed, 132 insertions, 32 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 48967a967890..8b73743b0b3f 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2337,6 +2337,8 @@ void evergreen_print_gpu_status_regs(struct radeon_device *rdev) | |||
2337 | RREG32(GRBM_STATUS_SE1)); | 2337 | RREG32(GRBM_STATUS_SE1)); |
2338 | dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", | 2338 | dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", |
2339 | RREG32(SRBM_STATUS)); | 2339 | RREG32(SRBM_STATUS)); |
2340 | dev_info(rdev->dev, " SRBM_STATUS2 = 0x%08X\n", | ||
2341 | RREG32(SRBM_STATUS2)); | ||
2340 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | 2342 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", |
2341 | RREG32(CP_STALLED_STAT1)); | 2343 | RREG32(CP_STALLED_STAT1)); |
2342 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | 2344 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", |
@@ -2349,28 +2351,111 @@ void evergreen_print_gpu_status_regs(struct radeon_device *rdev) | |||
2349 | RREG32(DMA_STATUS_REG)); | 2351 | RREG32(DMA_STATUS_REG)); |
2350 | } | 2352 | } |
2351 | 2353 | ||
2352 | static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | 2354 | static bool evergreen_is_display_hung(struct radeon_device *rdev) |
2353 | { | 2355 | { |
2354 | struct evergreen_mc_save save; | 2356 | u32 crtc_hung = 0; |
2355 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 2357 | u32 crtc_status[6]; |
2358 | u32 i, j, tmp; | ||
2359 | |||
2360 | for (i = 0; i < rdev->num_crtc; i++) { | ||
2361 | if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN) { | ||
2362 | crtc_status[i] = RREG32(EVERGREEN_CRTC_STATUS_HV_COUNT + crtc_offsets[i]); | ||
2363 | crtc_hung |= (1 << i); | ||
2364 | } | ||
2365 | } | ||
2366 | |||
2367 | for (j = 0; j < 10; j++) { | ||
2368 | for (i = 0; i < rdev->num_crtc; i++) { | ||
2369 | if (crtc_hung & (1 << i)) { | ||
2370 | tmp = RREG32(EVERGREEN_CRTC_STATUS_HV_COUNT + crtc_offsets[i]); | ||
2371 | if (tmp != crtc_status[i]) | ||
2372 | crtc_hung &= ~(1 << i); | ||
2373 | } | ||
2374 | } | ||
2375 | if (crtc_hung == 0) | ||
2376 | return false; | ||
2377 | udelay(100); | ||
2378 | } | ||
2379 | |||
2380 | return true; | ||
2381 | } | ||
2382 | |||
2383 | static u32 evergreen_gpu_check_soft_reset(struct radeon_device *rdev) | ||
2384 | { | ||
2385 | u32 reset_mask = 0; | ||
2356 | u32 tmp; | 2386 | u32 tmp; |
2357 | int ret = 0; | ||
2358 | 2387 | ||
2359 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | 2388 | /* GRBM_STATUS */ |
2360 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP); | 2389 | tmp = RREG32(GRBM_STATUS); |
2390 | if (tmp & (PA_BUSY | SC_BUSY | | ||
2391 | SH_BUSY | SX_BUSY | | ||
2392 | TA_BUSY | VGT_BUSY | | ||
2393 | DB_BUSY | CB_BUSY | | ||
2394 | SPI_BUSY | VGT_BUSY_NO_DMA)) | ||
2395 | reset_mask |= RADEON_RESET_GFX; | ||
2396 | |||
2397 | if (tmp & (CF_RQ_PENDING | PF_RQ_PENDING | | ||
2398 | CP_BUSY | CP_COHERENCY_BUSY)) | ||
2399 | reset_mask |= RADEON_RESET_CP; | ||
2400 | |||
2401 | if (tmp & GRBM_EE_BUSY) | ||
2402 | reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP; | ||
2361 | 2403 | ||
2362 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | 2404 | /* DMA_STATUS_REG */ |
2363 | reset_mask &= ~RADEON_RESET_DMA; | 2405 | tmp = RREG32(DMA_STATUS_REG); |
2406 | if (!(tmp & DMA_IDLE)) | ||
2407 | reset_mask |= RADEON_RESET_DMA; | ||
2408 | |||
2409 | /* SRBM_STATUS2 */ | ||
2410 | tmp = RREG32(SRBM_STATUS2); | ||
2411 | if (tmp & DMA_BUSY) | ||
2412 | reset_mask |= RADEON_RESET_DMA; | ||
2413 | |||
2414 | /* SRBM_STATUS */ | ||
2415 | tmp = RREG32(SRBM_STATUS); | ||
2416 | if (tmp & (RLC_RQ_PENDING | RLC_BUSY)) | ||
2417 | reset_mask |= RADEON_RESET_RLC; | ||
2418 | |||
2419 | if (tmp & IH_BUSY) | ||
2420 | reset_mask |= RADEON_RESET_IH; | ||
2421 | |||
2422 | if (tmp & SEM_BUSY) | ||
2423 | reset_mask |= RADEON_RESET_SEM; | ||
2424 | |||
2425 | if (tmp & GRBM_RQ_PENDING) | ||
2426 | reset_mask |= RADEON_RESET_GRBM; | ||
2427 | |||
2428 | if (tmp & VMC_BUSY) | ||
2429 | reset_mask |= RADEON_RESET_VMC; | ||
2430 | |||
2431 | if (tmp & (MCB_BUSY | MCB_NON_DISPLAY_BUSY | | ||
2432 | MCC_BUSY | MCD_BUSY)) | ||
2433 | reset_mask |= RADEON_RESET_MC; | ||
2434 | |||
2435 | if (evergreen_is_display_hung(rdev)) | ||
2436 | reset_mask |= RADEON_RESET_DISPLAY; | ||
2437 | |||
2438 | /* VM_L2_STATUS */ | ||
2439 | tmp = RREG32(VM_L2_STATUS); | ||
2440 | if (tmp & L2_BUSY) | ||
2441 | reset_mask |= RADEON_RESET_VMC; | ||
2442 | |||
2443 | return reset_mask; | ||
2444 | } | ||
2445 | |||
2446 | static void evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | ||
2447 | { | ||
2448 | struct evergreen_mc_save save; | ||
2449 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | ||
2450 | u32 tmp; | ||
2364 | 2451 | ||
2365 | if (reset_mask == 0) | 2452 | if (reset_mask == 0) |
2366 | return 0; | 2453 | return; |
2367 | 2454 | ||
2368 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); | 2455 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); |
2369 | 2456 | ||
2370 | evergreen_print_gpu_status_regs(rdev); | 2457 | evergreen_print_gpu_status_regs(rdev); |
2371 | 2458 | ||
2372 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
2373 | |||
2374 | evergreen_mc_stop(rdev, &save); | 2459 | evergreen_mc_stop(rdev, &save); |
2375 | if (evergreen_mc_wait_for_idle(rdev)) { | 2460 | if (evergreen_mc_wait_for_idle(rdev)) { |
2376 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 2461 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
@@ -2410,6 +2495,27 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2410 | if (reset_mask & RADEON_RESET_DMA) | 2495 | if (reset_mask & RADEON_RESET_DMA) |
2411 | srbm_soft_reset |= SOFT_RESET_DMA; | 2496 | srbm_soft_reset |= SOFT_RESET_DMA; |
2412 | 2497 | ||
2498 | if (reset_mask & RADEON_RESET_DISPLAY) | ||
2499 | srbm_soft_reset |= SOFT_RESET_DC; | ||
2500 | |||
2501 | if (reset_mask & RADEON_RESET_RLC) | ||
2502 | srbm_soft_reset |= SOFT_RESET_RLC; | ||
2503 | |||
2504 | if (reset_mask & RADEON_RESET_SEM) | ||
2505 | srbm_soft_reset |= SOFT_RESET_SEM; | ||
2506 | |||
2507 | if (reset_mask & RADEON_RESET_IH) | ||
2508 | srbm_soft_reset |= SOFT_RESET_IH; | ||
2509 | |||
2510 | if (reset_mask & RADEON_RESET_GRBM) | ||
2511 | srbm_soft_reset |= SOFT_RESET_GRBM; | ||
2512 | |||
2513 | if (reset_mask & RADEON_RESET_VMC) | ||
2514 | srbm_soft_reset |= SOFT_RESET_VMC; | ||
2515 | |||
2516 | if (reset_mask & RADEON_RESET_MC) | ||
2517 | srbm_soft_reset |= SOFT_RESET_MC; | ||
2518 | |||
2413 | if (grbm_soft_reset) { | 2519 | if (grbm_soft_reset) { |
2414 | tmp = RREG32(GRBM_SOFT_RESET); | 2520 | tmp = RREG32(GRBM_SOFT_RESET); |
2415 | tmp |= grbm_soft_reset; | 2521 | tmp |= grbm_soft_reset; |
@@ -2444,32 +2550,26 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2444 | evergreen_mc_resume(rdev, &save); | 2550 | evergreen_mc_resume(rdev, &save); |
2445 | udelay(50); | 2551 | udelay(50); |
2446 | 2552 | ||
2447 | #if 0 | ||
2448 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) { | ||
2449 | if (RREG32(GRBM_STATUS) & GUI_ACTIVE) | ||
2450 | ret = -EAGAIN; | ||
2451 | } | ||
2452 | |||
2453 | if (reset_mask & RADEON_RESET_DMA) { | ||
2454 | if (!(RREG32(DMA_STATUS_REG) & DMA_IDLE)) | ||
2455 | ret = -EAGAIN; | ||
2456 | } | ||
2457 | #endif | ||
2458 | |||
2459 | if (!ret) | ||
2460 | r600_set_bios_scratch_engine_hung(rdev, false); | ||
2461 | |||
2462 | evergreen_print_gpu_status_regs(rdev); | 2553 | evergreen_print_gpu_status_regs(rdev); |
2463 | |||
2464 | return 0; | ||
2465 | } | 2554 | } |
2466 | 2555 | ||
2467 | int evergreen_asic_reset(struct radeon_device *rdev) | 2556 | int evergreen_asic_reset(struct radeon_device *rdev) |
2468 | { | 2557 | { |
2469 | return evergreen_gpu_soft_reset(rdev, (RADEON_RESET_GFX | | 2558 | u32 reset_mask; |
2470 | RADEON_RESET_COMPUTE | | 2559 | |
2471 | RADEON_RESET_DMA | | 2560 | reset_mask = evergreen_gpu_check_soft_reset(rdev); |
2472 | RADEON_RESET_CP)); | 2561 | |
2562 | if (reset_mask) | ||
2563 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
2564 | |||
2565 | evergreen_gpu_soft_reset(rdev, reset_mask); | ||
2566 | |||
2567 | reset_mask = evergreen_gpu_check_soft_reset(rdev); | ||
2568 | |||
2569 | if (!reset_mask) | ||
2570 | r600_set_bios_scratch_engine_hung(rdev, false); | ||
2571 | |||
2572 | return 0; | ||
2473 | } | 2573 | } |
2474 | 2574 | ||
2475 | /* Interrupts */ | 2575 | /* Interrupts */ |