diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-01-18 18:12:22 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-01-31 16:24:52 -0500 |
commit | f13f7731a20ad2ceee8fa8a940b5a68abc733e06 (patch) | |
tree | f69b559daa3ffdab93c06b52b05b8513a43bc114 /drivers/gpu/drm/radeon | |
parent | 1c53467144c3af58f5dbccb13ff48466c2de0496 (diff) |
drm/radeon: use status regs to determine what to reset (6xx/7xx)
When we attempt the reset the GPU, look at the status registers
to determine what blocks need to be reset.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r-- | drivers/gpu/drm/radeon/r500_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 165 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 2 |
3 files changed, 136 insertions, 32 deletions
diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index ec576aaafb73..c0dc8d3ba0bb 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h | |||
@@ -355,6 +355,7 @@ | |||
355 | # define AVIVO_D1CRTC_V_BLANK (1 << 0) | 355 | # define AVIVO_D1CRTC_V_BLANK (1 << 0) |
356 | #define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 | 356 | #define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 |
357 | #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 | 357 | #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 |
358 | #define AVIVO_D1CRTC_STATUS_HV_COUNT 0x60ac | ||
358 | #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 | 359 | #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 |
359 | 360 | ||
360 | #define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4 | 361 | #define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4 |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 083eeb0b4fd1..997707b2a33e 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -94,6 +94,12 @@ MODULE_FIRMWARE("radeon/SUMO_me.bin"); | |||
94 | MODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); | 94 | MODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); |
95 | MODULE_FIRMWARE("radeon/SUMO2_me.bin"); | 95 | MODULE_FIRMWARE("radeon/SUMO2_me.bin"); |
96 | 96 | ||
97 | static const u32 crtc_offsets[2] = | ||
98 | { | ||
99 | 0, | ||
100 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL | ||
101 | }; | ||
102 | |||
97 | int r600_debugfs_mc_info_init(struct radeon_device *rdev); | 103 | int r600_debugfs_mc_info_init(struct radeon_device *rdev); |
98 | 104 | ||
99 | /* r600,rv610,rv630,rv620,rv635,rv670 */ | 105 | /* r600,rv610,rv630,rv620,rv635,rv670 */ |
@@ -1286,28 +1292,111 @@ static void r600_print_gpu_status_regs(struct radeon_device *rdev) | |||
1286 | RREG32(DMA_STATUS_REG)); | 1292 | RREG32(DMA_STATUS_REG)); |
1287 | } | 1293 | } |
1288 | 1294 | ||
1289 | static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | 1295 | static bool r600_is_display_hung(struct radeon_device *rdev) |
1290 | { | 1296 | { |
1291 | struct rv515_mc_save save; | 1297 | u32 crtc_hung = 0; |
1292 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 1298 | u32 crtc_status[2]; |
1299 | u32 i, j, tmp; | ||
1300 | |||
1301 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1302 | if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN) { | ||
1303 | crtc_status[i] = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); | ||
1304 | crtc_hung |= (1 << i); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | for (j = 0; j < 10; j++) { | ||
1309 | for (i = 0; i < rdev->num_crtc; i++) { | ||
1310 | if (crtc_hung & (1 << i)) { | ||
1311 | tmp = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); | ||
1312 | if (tmp != crtc_status[i]) | ||
1313 | crtc_hung &= ~(1 << i); | ||
1314 | } | ||
1315 | } | ||
1316 | if (crtc_hung == 0) | ||
1317 | return false; | ||
1318 | udelay(100); | ||
1319 | } | ||
1320 | |||
1321 | return true; | ||
1322 | } | ||
1323 | |||
1324 | static u32 r600_gpu_check_soft_reset(struct radeon_device *rdev) | ||
1325 | { | ||
1326 | u32 reset_mask = 0; | ||
1293 | u32 tmp; | 1327 | u32 tmp; |
1294 | int ret = 0; | ||
1295 | 1328 | ||
1296 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | 1329 | /* GRBM_STATUS */ |
1297 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP); | 1330 | tmp = RREG32(R_008010_GRBM_STATUS); |
1331 | if (rdev->family >= CHIP_RV770) { | ||
1332 | if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | | ||
1333 | G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | | ||
1334 | G_008010_TA_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | | ||
1335 | G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | | ||
1336 | G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) | ||
1337 | reset_mask |= RADEON_RESET_GFX; | ||
1338 | } else { | ||
1339 | if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | | ||
1340 | G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | | ||
1341 | G_008010_TA03_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | | ||
1342 | G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | | ||
1343 | G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) | ||
1344 | reset_mask |= RADEON_RESET_GFX; | ||
1345 | } | ||
1346 | |||
1347 | if (G_008010_CF_RQ_PENDING(tmp) | G_008010_PF_RQ_PENDING(tmp) | | ||
1348 | G_008010_CP_BUSY(tmp) | G_008010_CP_COHERENCY_BUSY(tmp)) | ||
1349 | reset_mask |= RADEON_RESET_CP; | ||
1350 | |||
1351 | if (G_008010_GRBM_EE_BUSY(tmp)) | ||
1352 | reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP; | ||
1353 | |||
1354 | /* DMA_STATUS_REG */ | ||
1355 | tmp = RREG32(DMA_STATUS_REG); | ||
1356 | if (!(tmp & DMA_IDLE)) | ||
1357 | reset_mask |= RADEON_RESET_DMA; | ||
1358 | |||
1359 | /* SRBM_STATUS */ | ||
1360 | tmp = RREG32(R_000E50_SRBM_STATUS); | ||
1361 | if (G_000E50_RLC_RQ_PENDING(tmp) | G_000E50_RLC_BUSY(tmp)) | ||
1362 | reset_mask |= RADEON_RESET_RLC; | ||
1363 | |||
1364 | if (G_000E50_IH_BUSY(tmp)) | ||
1365 | reset_mask |= RADEON_RESET_IH; | ||
1298 | 1366 | ||
1299 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | 1367 | if (G_000E50_SEM_BUSY(tmp)) |
1300 | reset_mask &= ~RADEON_RESET_DMA; | 1368 | reset_mask |= RADEON_RESET_SEM; |
1369 | |||
1370 | if (G_000E50_GRBM_RQ_PENDING(tmp)) | ||
1371 | reset_mask |= RADEON_RESET_GRBM; | ||
1372 | |||
1373 | if (G_000E50_VMC_BUSY(tmp)) | ||
1374 | reset_mask |= RADEON_RESET_VMC; | ||
1375 | |||
1376 | if (G_000E50_MCB_BUSY(tmp) | G_000E50_MCDZ_BUSY(tmp) | | ||
1377 | G_000E50_MCDY_BUSY(tmp) | G_000E50_MCDX_BUSY(tmp) | | ||
1378 | G_000E50_MCDW_BUSY(tmp)) | ||
1379 | reset_mask |= RADEON_RESET_MC; | ||
1380 | |||
1381 | if (r600_is_display_hung(rdev)) | ||
1382 | reset_mask |= RADEON_RESET_DISPLAY; | ||
1383 | |||
1384 | return reset_mask; | ||
1385 | } | ||
1386 | |||
1387 | static void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | ||
1388 | { | ||
1389 | struct rv515_mc_save save; | ||
1390 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | ||
1391 | u32 tmp; | ||
1301 | 1392 | ||
1302 | if (reset_mask == 0) | 1393 | if (reset_mask == 0) |
1303 | return 0; | 1394 | return; |
1304 | 1395 | ||
1305 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); | 1396 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); |
1306 | 1397 | ||
1307 | r600_print_gpu_status_regs(rdev); | 1398 | r600_print_gpu_status_regs(rdev); |
1308 | 1399 | ||
1309 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
1310 | |||
1311 | rv515_mc_stop(rdev, &save); | 1400 | rv515_mc_stop(rdev, &save); |
1312 | if (r600_mc_wait_for_idle(rdev)) { | 1401 | if (r600_mc_wait_for_idle(rdev)) { |
1313 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1402 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
@@ -1374,6 +1463,24 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1374 | srbm_soft_reset |= SOFT_RESET_DMA; | 1463 | srbm_soft_reset |= SOFT_RESET_DMA; |
1375 | } | 1464 | } |
1376 | 1465 | ||
1466 | if (reset_mask & RADEON_RESET_RLC) | ||
1467 | srbm_soft_reset |= S_000E60_SOFT_RESET_RLC(1); | ||
1468 | |||
1469 | if (reset_mask & RADEON_RESET_SEM) | ||
1470 | srbm_soft_reset |= S_000E60_SOFT_RESET_SEM(1); | ||
1471 | |||
1472 | if (reset_mask & RADEON_RESET_IH) | ||
1473 | srbm_soft_reset |= S_000E60_SOFT_RESET_IH(1); | ||
1474 | |||
1475 | if (reset_mask & RADEON_RESET_GRBM) | ||
1476 | srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); | ||
1477 | |||
1478 | if (reset_mask & RADEON_RESET_MC) | ||
1479 | srbm_soft_reset |= S_000E60_SOFT_RESET_MC(1); | ||
1480 | |||
1481 | if (reset_mask & RADEON_RESET_VMC) | ||
1482 | srbm_soft_reset |= S_000E60_SOFT_RESET_VMC(1); | ||
1483 | |||
1377 | if (grbm_soft_reset) { | 1484 | if (grbm_soft_reset) { |
1378 | tmp = RREG32(R_008020_GRBM_SOFT_RESET); | 1485 | tmp = RREG32(R_008020_GRBM_SOFT_RESET); |
1379 | tmp |= grbm_soft_reset; | 1486 | tmp |= grbm_soft_reset; |
@@ -1408,32 +1515,26 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1408 | rv515_mc_resume(rdev, &save); | 1515 | rv515_mc_resume(rdev, &save); |
1409 | udelay(50); | 1516 | udelay(50); |
1410 | 1517 | ||
1411 | #if 0 | ||
1412 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP)) { | ||
1413 | if (RREG32(GRBM_STATUS) & GUI_ACTIVE) | ||
1414 | ret = -EAGAIN; | ||
1415 | } | ||
1416 | |||
1417 | if (reset_mask & RADEON_RESET_DMA) { | ||
1418 | if (!(RREG32(DMA_STATUS_REG) & DMA_IDLE)) | ||
1419 | ret = -EAGAIN; | ||
1420 | } | ||
1421 | #endif | ||
1422 | |||
1423 | if (!ret) | ||
1424 | r600_set_bios_scratch_engine_hung(rdev, false); | ||
1425 | |||
1426 | r600_print_gpu_status_regs(rdev); | 1518 | r600_print_gpu_status_regs(rdev); |
1427 | |||
1428 | return ret; | ||
1429 | } | 1519 | } |
1430 | 1520 | ||
1431 | int r600_asic_reset(struct radeon_device *rdev) | 1521 | int r600_asic_reset(struct radeon_device *rdev) |
1432 | { | 1522 | { |
1433 | return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX | | 1523 | u32 reset_mask; |
1434 | RADEON_RESET_COMPUTE | | 1524 | |
1435 | RADEON_RESET_DMA | | 1525 | reset_mask = r600_gpu_check_soft_reset(rdev); |
1436 | RADEON_RESET_CP)); | 1526 | |
1527 | if (reset_mask) | ||
1528 | r600_set_bios_scratch_engine_hung(rdev, true); | ||
1529 | |||
1530 | r600_gpu_soft_reset(rdev, reset_mask); | ||
1531 | |||
1532 | reset_mask = r600_gpu_check_soft_reset(rdev); | ||
1533 | |||
1534 | if (!reset_mask) | ||
1535 | r600_set_bios_scratch_engine_hung(rdev, false); | ||
1536 | |||
1537 | return 0; | ||
1437 | } | 1538 | } |
1438 | 1539 | ||
1439 | bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | 1540 | bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 494ef768966f..a42ba11a3bed 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -1321,6 +1321,7 @@ | |||
1321 | #define G_008010_VC_BUSY(x) (((x) >> 11) & 1) | 1321 | #define G_008010_VC_BUSY(x) (((x) >> 11) & 1) |
1322 | #define G_008010_DB03_CLEAN(x) (((x) >> 12) & 1) | 1322 | #define G_008010_DB03_CLEAN(x) (((x) >> 12) & 1) |
1323 | #define G_008010_CB03_CLEAN(x) (((x) >> 13) & 1) | 1323 | #define G_008010_CB03_CLEAN(x) (((x) >> 13) & 1) |
1324 | #define G_008010_TA_BUSY(x) (((x) >> 14) & 1) | ||
1324 | #define G_008010_VGT_BUSY_NO_DMA(x) (((x) >> 16) & 1) | 1325 | #define G_008010_VGT_BUSY_NO_DMA(x) (((x) >> 16) & 1) |
1325 | #define G_008010_VGT_BUSY(x) (((x) >> 17) & 1) | 1326 | #define G_008010_VGT_BUSY(x) (((x) >> 17) & 1) |
1326 | #define G_008010_TA03_BUSY(x) (((x) >> 18) & 1) | 1327 | #define G_008010_TA03_BUSY(x) (((x) >> 18) & 1) |
@@ -1388,6 +1389,7 @@ | |||
1388 | #define G_000E50_MCDW_BUSY(x) (((x) >> 13) & 1) | 1389 | #define G_000E50_MCDW_BUSY(x) (((x) >> 13) & 1) |
1389 | #define G_000E50_SEM_BUSY(x) (((x) >> 14) & 1) | 1390 | #define G_000E50_SEM_BUSY(x) (((x) >> 14) & 1) |
1390 | #define G_000E50_RLC_BUSY(x) (((x) >> 15) & 1) | 1391 | #define G_000E50_RLC_BUSY(x) (((x) >> 15) & 1) |
1392 | #define G_000E50_IH_BUSY(x) (((x) >> 17) & 1) | ||
1391 | #define G_000E50_BIF_BUSY(x) (((x) >> 29) & 1) | 1393 | #define G_000E50_BIF_BUSY(x) (((x) >> 29) & 1) |
1392 | #define R_000E60_SRBM_SOFT_RESET 0x0E60 | 1394 | #define R_000E60_SRBM_SOFT_RESET 0x0E60 |
1393 | #define S_000E60_SOFT_RESET_BIF(x) (((x) & 1) << 1) | 1395 | #define S_000E60_SOFT_RESET_BIF(x) (((x) & 1) << 1) |