diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-01-18 14:51:38 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-01-31 16:24:51 -0500 |
commit | 187e359311ac101c3a0c5078e161d64789ef16e0 (patch) | |
tree | 3139be3099cd69709386f61dcd34abdd04a74dc7 /drivers/gpu/drm/radeon/ni.c | |
parent | b7630473def7dad61728c68b4f23d0f2294405bc (diff) |
drm/radeon: rework GPU reset on cayman/TN
Update the code to better match the recommended
programming sequence for soft reset.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/ni.c')
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 198 |
1 files changed, 91 insertions, 107 deletions
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index af9e86d2fc07..88f6fbbe4be6 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "ni_reg.h" | 34 | #include "ni_reg.h" |
35 | #include "cayman_blit_shaders.h" | 35 | #include "cayman_blit_shaders.h" |
36 | 36 | ||
37 | extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); | ||
37 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); | 38 | extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); |
38 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); | 39 | extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); |
39 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); | 40 | extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); |
@@ -1310,111 +1311,15 @@ void cayman_dma_fini(struct radeon_device *rdev) | |||
1310 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]); | 1311 | radeon_ring_fini(rdev, &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX]); |
1311 | } | 1312 | } |
1312 | 1313 | ||
1313 | static void cayman_gpu_soft_reset_gfx(struct radeon_device *rdev) | ||
1314 | { | ||
1315 | u32 grbm_reset = 0; | ||
1316 | |||
1317 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1318 | return; | ||
1319 | |||
1320 | dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", | ||
1321 | RREG32(GRBM_STATUS)); | ||
1322 | dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", | ||
1323 | RREG32(GRBM_STATUS_SE0)); | ||
1324 | dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", | ||
1325 | RREG32(GRBM_STATUS_SE1)); | ||
1326 | dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", | ||
1327 | RREG32(SRBM_STATUS)); | ||
1328 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
1329 | RREG32(CP_STALLED_STAT1)); | ||
1330 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
1331 | RREG32(CP_STALLED_STAT2)); | ||
1332 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
1333 | RREG32(CP_BUSY_STAT)); | ||
1334 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
1335 | RREG32(CP_STAT)); | ||
1336 | |||
1337 | /* Disable CP parsing/prefetching */ | ||
1338 | WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); | ||
1339 | |||
1340 | /* reset all the gfx blocks */ | ||
1341 | grbm_reset = (SOFT_RESET_CP | | ||
1342 | SOFT_RESET_CB | | ||
1343 | SOFT_RESET_DB | | ||
1344 | SOFT_RESET_GDS | | ||
1345 | SOFT_RESET_PA | | ||
1346 | SOFT_RESET_SC | | ||
1347 | SOFT_RESET_SPI | | ||
1348 | SOFT_RESET_SH | | ||
1349 | SOFT_RESET_SX | | ||
1350 | SOFT_RESET_TC | | ||
1351 | SOFT_RESET_TA | | ||
1352 | SOFT_RESET_VGT | | ||
1353 | SOFT_RESET_IA); | ||
1354 | |||
1355 | dev_info(rdev->dev, " GRBM_SOFT_RESET=0x%08X\n", grbm_reset); | ||
1356 | WREG32(GRBM_SOFT_RESET, grbm_reset); | ||
1357 | (void)RREG32(GRBM_SOFT_RESET); | ||
1358 | udelay(50); | ||
1359 | WREG32(GRBM_SOFT_RESET, 0); | ||
1360 | (void)RREG32(GRBM_SOFT_RESET); | ||
1361 | |||
1362 | dev_info(rdev->dev, " GRBM_STATUS = 0x%08X\n", | ||
1363 | RREG32(GRBM_STATUS)); | ||
1364 | dev_info(rdev->dev, " GRBM_STATUS_SE0 = 0x%08X\n", | ||
1365 | RREG32(GRBM_STATUS_SE0)); | ||
1366 | dev_info(rdev->dev, " GRBM_STATUS_SE1 = 0x%08X\n", | ||
1367 | RREG32(GRBM_STATUS_SE1)); | ||
1368 | dev_info(rdev->dev, " SRBM_STATUS = 0x%08X\n", | ||
1369 | RREG32(SRBM_STATUS)); | ||
1370 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
1371 | RREG32(CP_STALLED_STAT1)); | ||
1372 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
1373 | RREG32(CP_STALLED_STAT2)); | ||
1374 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
1375 | RREG32(CP_BUSY_STAT)); | ||
1376 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
1377 | RREG32(CP_STAT)); | ||
1378 | |||
1379 | } | ||
1380 | |||
1381 | static void cayman_gpu_soft_reset_dma(struct radeon_device *rdev) | ||
1382 | { | ||
1383 | u32 tmp; | ||
1384 | |||
1385 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1386 | return; | ||
1387 | |||
1388 | dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", | ||
1389 | RREG32(DMA_STATUS_REG)); | ||
1390 | |||
1391 | /* dma0 */ | ||
1392 | tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); | ||
1393 | tmp &= ~DMA_RB_ENABLE; | ||
1394 | WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); | ||
1395 | |||
1396 | /* dma1 */ | ||
1397 | tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); | ||
1398 | tmp &= ~DMA_RB_ENABLE; | ||
1399 | WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); | ||
1400 | |||
1401 | /* Reset dma */ | ||
1402 | WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA | SOFT_RESET_DMA1); | ||
1403 | RREG32(SRBM_SOFT_RESET); | ||
1404 | udelay(50); | ||
1405 | WREG32(SRBM_SOFT_RESET, 0); | ||
1406 | |||
1407 | dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", | ||
1408 | RREG32(DMA_STATUS_REG)); | ||
1409 | |||
1410 | } | ||
1411 | |||
1412 | static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | 1314 | static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) |
1413 | { | 1315 | { |
1414 | struct evergreen_mc_save save; | 1316 | struct evergreen_mc_save save; |
1317 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | ||
1318 | u32 tmp; | ||
1319 | int ret = 0; | ||
1415 | 1320 | ||
1416 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | 1321 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) |
1417 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | 1322 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP); |
1418 | 1323 | ||
1419 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | 1324 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) |
1420 | reset_mask &= ~RADEON_RESET_DMA; | 1325 | reset_mask &= ~RADEON_RESET_DMA; |
@@ -1422,10 +1327,9 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1422 | if (reset_mask == 0) | 1327 | if (reset_mask == 0) |
1423 | return 0; | 1328 | return 0; |
1424 | 1329 | ||
1425 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
1426 | |||
1427 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); | 1330 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); |
1428 | 1331 | ||
1332 | evergreen_print_gpu_status_regs(rdev); | ||
1429 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", | 1333 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", |
1430 | RREG32(0x14F8)); | 1334 | RREG32(0x14F8)); |
1431 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", | 1335 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", |
@@ -1435,23 +1339,102 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1435 | dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", | 1339 | dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", |
1436 | RREG32(0x14DC)); | 1340 | RREG32(0x14DC)); |
1437 | 1341 | ||
1342 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
1343 | |||
1438 | evergreen_mc_stop(rdev, &save); | 1344 | evergreen_mc_stop(rdev, &save); |
1439 | if (evergreen_mc_wait_for_idle(rdev)) { | 1345 | if (evergreen_mc_wait_for_idle(rdev)) { |
1440 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1346 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
1441 | } | 1347 | } |
1442 | 1348 | ||
1443 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) | 1349 | /* Disable CP parsing/prefetching */ |
1444 | cayman_gpu_soft_reset_gfx(rdev); | 1350 | WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT); |
1351 | |||
1352 | if (reset_mask & RADEON_RESET_DMA) { | ||
1353 | /* dma0 */ | ||
1354 | tmp = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); | ||
1355 | tmp &= ~DMA_RB_ENABLE; | ||
1356 | WREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET, tmp); | ||
1357 | |||
1358 | /* dma1 */ | ||
1359 | tmp = RREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET); | ||
1360 | tmp &= ~DMA_RB_ENABLE; | ||
1361 | WREG32(DMA_RB_CNTL + DMA1_REGISTER_OFFSET, tmp); | ||
1362 | } | ||
1363 | |||
1364 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) { | ||
1365 | grbm_soft_reset = SOFT_RESET_CB | | ||
1366 | SOFT_RESET_DB | | ||
1367 | SOFT_RESET_GDS | | ||
1368 | SOFT_RESET_PA | | ||
1369 | SOFT_RESET_SC | | ||
1370 | SOFT_RESET_SPI | | ||
1371 | SOFT_RESET_SH | | ||
1372 | SOFT_RESET_SX | | ||
1373 | SOFT_RESET_TC | | ||
1374 | SOFT_RESET_TA | | ||
1375 | SOFT_RESET_VGT | | ||
1376 | SOFT_RESET_IA; | ||
1377 | } | ||
1378 | |||
1379 | if (reset_mask & RADEON_RESET_CP) { | ||
1380 | grbm_soft_reset |= SOFT_RESET_CP | SOFT_RESET_VGT; | ||
1381 | |||
1382 | srbm_soft_reset |= SOFT_RESET_GRBM; | ||
1383 | } | ||
1445 | 1384 | ||
1446 | if (reset_mask & RADEON_RESET_DMA) | 1385 | if (reset_mask & RADEON_RESET_DMA) |
1447 | cayman_gpu_soft_reset_dma(rdev); | 1386 | srbm_soft_reset |= SOFT_RESET_DMA | SOFT_RESET_DMA1; |
1387 | |||
1388 | if (grbm_soft_reset) { | ||
1389 | tmp = RREG32(GRBM_SOFT_RESET); | ||
1390 | tmp |= grbm_soft_reset; | ||
1391 | dev_info(rdev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1392 | WREG32(GRBM_SOFT_RESET, tmp); | ||
1393 | tmp = RREG32(GRBM_SOFT_RESET); | ||
1394 | |||
1395 | udelay(50); | ||
1396 | |||
1397 | tmp &= ~grbm_soft_reset; | ||
1398 | WREG32(GRBM_SOFT_RESET, tmp); | ||
1399 | tmp = RREG32(GRBM_SOFT_RESET); | ||
1400 | } | ||
1401 | |||
1402 | if (srbm_soft_reset) { | ||
1403 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1404 | tmp |= srbm_soft_reset; | ||
1405 | dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1406 | WREG32(SRBM_SOFT_RESET, tmp); | ||
1407 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1408 | |||
1409 | udelay(50); | ||
1410 | |||
1411 | tmp &= ~srbm_soft_reset; | ||
1412 | WREG32(SRBM_SOFT_RESET, tmp); | ||
1413 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1414 | } | ||
1448 | 1415 | ||
1449 | /* Wait a little for things to settle down */ | 1416 | /* Wait a little for things to settle down */ |
1450 | udelay(50); | 1417 | udelay(50); |
1451 | 1418 | ||
1452 | evergreen_mc_resume(rdev, &save); | 1419 | evergreen_mc_resume(rdev, &save); |
1420 | udelay(50); | ||
1421 | |||
1422 | #if 0 | ||
1423 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) { | ||
1424 | if (RREG32(GRBM_STATUS) & GUI_ACTIVE) | ||
1425 | ret = -EAGAIN; | ||
1426 | } | ||
1427 | |||
1428 | if (reset_mask & RADEON_RESET_DMA) { | ||
1429 | if (!(RREG32(DMA_STATUS_REG) & DMA_IDLE)) | ||
1430 | ret = -EAGAIN; | ||
1431 | } | ||
1432 | #endif | ||
1433 | |||
1434 | if (!ret) | ||
1435 | r600_set_bios_scratch_engine_hung(rdev, false); | ||
1453 | 1436 | ||
1454 | r600_set_bios_scratch_engine_hung(rdev, false); | 1437 | evergreen_print_gpu_status_regs(rdev); |
1455 | 1438 | ||
1456 | return 0; | 1439 | return 0; |
1457 | } | 1440 | } |
@@ -1460,7 +1443,8 @@ int cayman_asic_reset(struct radeon_device *rdev) | |||
1460 | { | 1443 | { |
1461 | return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX | | 1444 | return cayman_gpu_soft_reset(rdev, (RADEON_RESET_GFX | |
1462 | RADEON_RESET_COMPUTE | | 1445 | RADEON_RESET_COMPUTE | |
1463 | RADEON_RESET_DMA)); | 1446 | RADEON_RESET_DMA | |
1447 | RADEON_RESET_CP)); | ||
1464 | } | 1448 | } |
1465 | 1449 | ||
1466 | /** | 1450 | /** |