diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-01-18 13:53:37 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-01-31 16:24:49 -0500 |
commit | d3cb781e83b39561f717358e95d357e53a0da720 (patch) | |
tree | 35681fcb7b3d1d9c6016600b6078abadbec6f6a6 /drivers | |
parent | 410a3418a88cc1273a281d347687f736fc39dd86 (diff) |
drm/radeon: rework GPU reset on r6xx/r7xx
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')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 249 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 2 |
2 files changed, 129 insertions, 122 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index a6208178a6f2..083eeb0b4fd1 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1266,122 +1266,22 @@ void r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung) | |||
1266 | WREG32(R600_BIOS_3_SCRATCH, tmp); | 1266 | WREG32(R600_BIOS_3_SCRATCH, tmp); |
1267 | } | 1267 | } |
1268 | 1268 | ||
1269 | /* We doesn't check that the GPU really needs a reset we simply do the | 1269 | static void r600_print_gpu_status_regs(struct radeon_device *rdev) |
1270 | * reset, it's up to the caller to determine if the GPU needs one. We | ||
1271 | * might add an helper function to check that. | ||
1272 | */ | ||
1273 | static void r600_gpu_soft_reset_gfx(struct radeon_device *rdev) | ||
1274 | { | 1270 | { |
1275 | u32 grbm_busy_mask = S_008010_VC_BUSY(1) | S_008010_VGT_BUSY_NO_DMA(1) | | ||
1276 | S_008010_VGT_BUSY(1) | S_008010_TA03_BUSY(1) | | ||
1277 | S_008010_TC_BUSY(1) | S_008010_SX_BUSY(1) | | ||
1278 | S_008010_SH_BUSY(1) | S_008010_SPI03_BUSY(1) | | ||
1279 | S_008010_SMX_BUSY(1) | S_008010_SC_BUSY(1) | | ||
1280 | S_008010_PA_BUSY(1) | S_008010_DB03_BUSY(1) | | ||
1281 | S_008010_CR_BUSY(1) | S_008010_CB03_BUSY(1) | | ||
1282 | S_008010_GUI_ACTIVE(1); | ||
1283 | u32 grbm2_busy_mask = S_008014_SPI0_BUSY(1) | S_008014_SPI1_BUSY(1) | | ||
1284 | S_008014_SPI2_BUSY(1) | S_008014_SPI3_BUSY(1) | | ||
1285 | S_008014_TA0_BUSY(1) | S_008014_TA1_BUSY(1) | | ||
1286 | S_008014_TA2_BUSY(1) | S_008014_TA3_BUSY(1) | | ||
1287 | S_008014_DB0_BUSY(1) | S_008014_DB1_BUSY(1) | | ||
1288 | S_008014_DB2_BUSY(1) | S_008014_DB3_BUSY(1) | | ||
1289 | S_008014_CB0_BUSY(1) | S_008014_CB1_BUSY(1) | | ||
1290 | S_008014_CB2_BUSY(1) | S_008014_CB3_BUSY(1); | ||
1291 | u32 tmp; | ||
1292 | |||
1293 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1294 | return; | ||
1295 | |||
1296 | dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", | ||
1297 | RREG32(R_008010_GRBM_STATUS)); | ||
1298 | dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", | ||
1299 | RREG32(R_008014_GRBM_STATUS2)); | ||
1300 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", | ||
1301 | RREG32(R_000E50_SRBM_STATUS)); | ||
1302 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | ||
1303 | RREG32(CP_STALLED_STAT1)); | ||
1304 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | ||
1305 | RREG32(CP_STALLED_STAT2)); | ||
1306 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | ||
1307 | RREG32(CP_BUSY_STAT)); | ||
1308 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | ||
1309 | RREG32(CP_STAT)); | ||
1310 | |||
1311 | /* Disable CP parsing/prefetching */ | ||
1312 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | ||
1313 | |||
1314 | /* Check if any of the rendering block is busy and reset it */ | ||
1315 | if ((RREG32(R_008010_GRBM_STATUS) & grbm_busy_mask) || | ||
1316 | (RREG32(R_008014_GRBM_STATUS2) & grbm2_busy_mask)) { | ||
1317 | tmp = S_008020_SOFT_RESET_CR(1) | | ||
1318 | S_008020_SOFT_RESET_DB(1) | | ||
1319 | S_008020_SOFT_RESET_CB(1) | | ||
1320 | S_008020_SOFT_RESET_PA(1) | | ||
1321 | S_008020_SOFT_RESET_SC(1) | | ||
1322 | S_008020_SOFT_RESET_SMX(1) | | ||
1323 | S_008020_SOFT_RESET_SPI(1) | | ||
1324 | S_008020_SOFT_RESET_SX(1) | | ||
1325 | S_008020_SOFT_RESET_SH(1) | | ||
1326 | S_008020_SOFT_RESET_TC(1) | | ||
1327 | S_008020_SOFT_RESET_TA(1) | | ||
1328 | S_008020_SOFT_RESET_VC(1) | | ||
1329 | S_008020_SOFT_RESET_VGT(1); | ||
1330 | dev_info(rdev->dev, " R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1331 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | ||
1332 | RREG32(R_008020_GRBM_SOFT_RESET); | ||
1333 | mdelay(15); | ||
1334 | WREG32(R_008020_GRBM_SOFT_RESET, 0); | ||
1335 | } | ||
1336 | /* Reset CP (we always reset CP) */ | ||
1337 | tmp = S_008020_SOFT_RESET_CP(1); | ||
1338 | dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1339 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | ||
1340 | RREG32(R_008020_GRBM_SOFT_RESET); | ||
1341 | mdelay(15); | ||
1342 | WREG32(R_008020_GRBM_SOFT_RESET, 0); | ||
1343 | |||
1344 | dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", | 1271 | dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", |
1345 | RREG32(R_008010_GRBM_STATUS)); | 1272 | RREG32(R_008010_GRBM_STATUS)); |
1346 | dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", | 1273 | dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", |
1347 | RREG32(R_008014_GRBM_STATUS2)); | 1274 | RREG32(R_008014_GRBM_STATUS2)); |
1348 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", | 1275 | dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", |
1349 | RREG32(R_000E50_SRBM_STATUS)); | 1276 | RREG32(R_000E50_SRBM_STATUS)); |
1350 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", | 1277 | dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", |
1351 | RREG32(CP_STALLED_STAT1)); | 1278 | RREG32(CP_STALLED_STAT1)); |
1352 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", | 1279 | dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", |
1353 | RREG32(CP_STALLED_STAT2)); | 1280 | RREG32(CP_STALLED_STAT2)); |
1354 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", | 1281 | dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", |
1355 | RREG32(CP_BUSY_STAT)); | 1282 | RREG32(CP_BUSY_STAT)); |
1356 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", | 1283 | dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", |
1357 | RREG32(CP_STAT)); | 1284 | RREG32(CP_STAT)); |
1358 | |||
1359 | } | ||
1360 | |||
1361 | static void r600_gpu_soft_reset_dma(struct radeon_device *rdev) | ||
1362 | { | ||
1363 | u32 tmp; | ||
1364 | |||
1365 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1366 | return; | ||
1367 | |||
1368 | dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", | ||
1369 | RREG32(DMA_STATUS_REG)); | ||
1370 | |||
1371 | /* Disable DMA */ | ||
1372 | tmp = RREG32(DMA_RB_CNTL); | ||
1373 | tmp &= ~DMA_RB_ENABLE; | ||
1374 | WREG32(DMA_RB_CNTL, tmp); | ||
1375 | |||
1376 | /* Reset dma */ | ||
1377 | if (rdev->family >= CHIP_RV770) | ||
1378 | WREG32(SRBM_SOFT_RESET, RV770_SOFT_RESET_DMA); | ||
1379 | else | ||
1380 | WREG32(SRBM_SOFT_RESET, SOFT_RESET_DMA); | ||
1381 | RREG32(SRBM_SOFT_RESET); | ||
1382 | udelay(50); | ||
1383 | WREG32(SRBM_SOFT_RESET, 0); | ||
1384 | |||
1385 | dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", | 1285 | dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", |
1386 | RREG32(DMA_STATUS_REG)); | 1286 | RREG32(DMA_STATUS_REG)); |
1387 | } | 1287 | } |
@@ -1389,9 +1289,12 @@ static void r600_gpu_soft_reset_dma(struct radeon_device *rdev) | |||
1389 | static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | 1289 | static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) |
1390 | { | 1290 | { |
1391 | struct rv515_mc_save save; | 1291 | struct rv515_mc_save save; |
1292 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | ||
1293 | u32 tmp; | ||
1294 | int ret = 0; | ||
1392 | 1295 | ||
1393 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | 1296 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) |
1394 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | 1297 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE | RADEON_RESET_CP); |
1395 | 1298 | ||
1396 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | 1299 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) |
1397 | reset_mask &= ~RADEON_RESET_DMA; | 1300 | reset_mask &= ~RADEON_RESET_DMA; |
@@ -1401,6 +1304,8 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1401 | 1304 | ||
1402 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); | 1305 | dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); |
1403 | 1306 | ||
1307 | r600_print_gpu_status_regs(rdev); | ||
1308 | |||
1404 | r600_set_bios_scratch_engine_hung(rdev, true); | 1309 | r600_set_bios_scratch_engine_hung(rdev, true); |
1405 | 1310 | ||
1406 | rv515_mc_stop(rdev, &save); | 1311 | rv515_mc_stop(rdev, &save); |
@@ -1408,20 +1313,127 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1408 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1313 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
1409 | } | 1314 | } |
1410 | 1315 | ||
1411 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) | 1316 | /* Disable CP parsing/prefetching */ |
1412 | r600_gpu_soft_reset_gfx(rdev); | 1317 | if (rdev->family >= CHIP_RV770) |
1318 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); | ||
1319 | else | ||
1320 | WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); | ||
1321 | |||
1322 | /* disable the RLC */ | ||
1323 | WREG32(RLC_CNTL, 0); | ||
1324 | |||
1325 | if (reset_mask & RADEON_RESET_DMA) { | ||
1326 | /* Disable DMA */ | ||
1327 | tmp = RREG32(DMA_RB_CNTL); | ||
1328 | tmp &= ~DMA_RB_ENABLE; | ||
1329 | WREG32(DMA_RB_CNTL, tmp); | ||
1330 | } | ||
1331 | |||
1332 | mdelay(50); | ||
1333 | |||
1334 | if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) { | ||
1335 | if (rdev->family >= CHIP_RV770) | ||
1336 | grbm_soft_reset |= S_008020_SOFT_RESET_DB(1) | | ||
1337 | S_008020_SOFT_RESET_CB(1) | | ||
1338 | S_008020_SOFT_RESET_PA(1) | | ||
1339 | S_008020_SOFT_RESET_SC(1) | | ||
1340 | S_008020_SOFT_RESET_SPI(1) | | ||
1341 | S_008020_SOFT_RESET_SX(1) | | ||
1342 | S_008020_SOFT_RESET_SH(1) | | ||
1343 | S_008020_SOFT_RESET_TC(1) | | ||
1344 | S_008020_SOFT_RESET_TA(1) | | ||
1345 | S_008020_SOFT_RESET_VC(1) | | ||
1346 | S_008020_SOFT_RESET_VGT(1); | ||
1347 | else | ||
1348 | grbm_soft_reset |= S_008020_SOFT_RESET_CR(1) | | ||
1349 | S_008020_SOFT_RESET_DB(1) | | ||
1350 | S_008020_SOFT_RESET_CB(1) | | ||
1351 | S_008020_SOFT_RESET_PA(1) | | ||
1352 | S_008020_SOFT_RESET_SC(1) | | ||
1353 | S_008020_SOFT_RESET_SMX(1) | | ||
1354 | S_008020_SOFT_RESET_SPI(1) | | ||
1355 | S_008020_SOFT_RESET_SX(1) | | ||
1356 | S_008020_SOFT_RESET_SH(1) | | ||
1357 | S_008020_SOFT_RESET_TC(1) | | ||
1358 | S_008020_SOFT_RESET_TA(1) | | ||
1359 | S_008020_SOFT_RESET_VC(1) | | ||
1360 | S_008020_SOFT_RESET_VGT(1); | ||
1361 | } | ||
1362 | |||
1363 | if (reset_mask & RADEON_RESET_CP) { | ||
1364 | grbm_soft_reset |= S_008020_SOFT_RESET_CP(1) | | ||
1365 | S_008020_SOFT_RESET_VGT(1); | ||
1413 | 1366 | ||
1414 | if (reset_mask & RADEON_RESET_DMA) | 1367 | srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); |
1415 | r600_gpu_soft_reset_dma(rdev); | 1368 | } |
1369 | |||
1370 | if (reset_mask & RADEON_RESET_DMA) { | ||
1371 | if (rdev->family >= CHIP_RV770) | ||
1372 | srbm_soft_reset |= RV770_SOFT_RESET_DMA; | ||
1373 | else | ||
1374 | srbm_soft_reset |= SOFT_RESET_DMA; | ||
1375 | } | ||
1376 | |||
1377 | if (grbm_soft_reset) { | ||
1378 | tmp = RREG32(R_008020_GRBM_SOFT_RESET); | ||
1379 | tmp |= grbm_soft_reset; | ||
1380 | dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1381 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | ||
1382 | tmp = RREG32(R_008020_GRBM_SOFT_RESET); | ||
1383 | |||
1384 | udelay(50); | ||
1385 | |||
1386 | tmp &= ~grbm_soft_reset; | ||
1387 | WREG32(R_008020_GRBM_SOFT_RESET, tmp); | ||
1388 | tmp = RREG32(R_008020_GRBM_SOFT_RESET); | ||
1389 | } | ||
1390 | |||
1391 | if (srbm_soft_reset) { | ||
1392 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1393 | tmp |= srbm_soft_reset; | ||
1394 | dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); | ||
1395 | WREG32(SRBM_SOFT_RESET, tmp); | ||
1396 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1397 | |||
1398 | udelay(50); | ||
1399 | |||
1400 | tmp &= ~srbm_soft_reset; | ||
1401 | WREG32(SRBM_SOFT_RESET, tmp); | ||
1402 | tmp = RREG32(SRBM_SOFT_RESET); | ||
1403 | } | ||
1416 | 1404 | ||
1417 | /* Wait a little for things to settle down */ | 1405 | /* Wait a little for things to settle down */ |
1418 | mdelay(1); | 1406 | mdelay(1); |
1419 | 1407 | ||
1420 | rv515_mc_resume(rdev, &save); | 1408 | rv515_mc_resume(rdev, &save); |
1409 | udelay(50); | ||
1421 | 1410 | ||
1422 | r600_set_bios_scratch_engine_hung(rdev, false); | 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 | } | ||
1423 | 1416 | ||
1424 | return 0; | 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); | ||
1427 | |||
1428 | return ret; | ||
1429 | } | ||
1430 | |||
1431 | int r600_asic_reset(struct radeon_device *rdev) | ||
1432 | { | ||
1433 | return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX | | ||
1434 | RADEON_RESET_COMPUTE | | ||
1435 | RADEON_RESET_DMA | | ||
1436 | RADEON_RESET_CP)); | ||
1425 | } | 1437 | } |
1426 | 1438 | ||
1427 | bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | 1439 | bool r600_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) |
@@ -1465,13 +1477,6 @@ bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
1465 | return radeon_ring_test_lockup(rdev, ring); | 1477 | return radeon_ring_test_lockup(rdev, ring); |
1466 | } | 1478 | } |
1467 | 1479 | ||
1468 | int r600_asic_reset(struct radeon_device *rdev) | ||
1469 | { | ||
1470 | return r600_gpu_soft_reset(rdev, (RADEON_RESET_GFX | | ||
1471 | RADEON_RESET_COMPUTE | | ||
1472 | RADEON_RESET_DMA)); | ||
1473 | } | ||
1474 | |||
1475 | u32 r6xx_remap_render_backend(struct radeon_device *rdev, | 1480 | u32 r6xx_remap_render_backend(struct radeon_device *rdev, |
1476 | u32 tiling_pipe_num, | 1481 | u32 tiling_pipe_num, |
1477 | u32 max_rb_num, | 1482 | u32 max_rb_num, |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 62423b0eb2b9..494ef768966f 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -182,6 +182,8 @@ | |||
182 | #define CP_COHER_BASE 0x85F8 | 182 | #define CP_COHER_BASE 0x85F8 |
183 | #define CP_DEBUG 0xC1FC | 183 | #define CP_DEBUG 0xC1FC |
184 | #define R_0086D8_CP_ME_CNTL 0x86D8 | 184 | #define R_0086D8_CP_ME_CNTL 0x86D8 |
185 | #define S_0086D8_CP_PFP_HALT(x) (((x) & 1)<<26) | ||
186 | #define C_0086D8_CP_PFP_HALT(x) ((x) & 0xFBFFFFFF) | ||
185 | #define S_0086D8_CP_ME_HALT(x) (((x) & 1)<<28) | 187 | #define S_0086D8_CP_ME_HALT(x) (((x) & 1)<<28) |
186 | #define C_0086D8_CP_ME_HALT(x) ((x) & 0xEFFFFFFF) | 188 | #define C_0086D8_CP_ME_HALT(x) ((x) & 0xEFFFFFFF) |
187 | #define CP_ME_RAM_DATA 0xC160 | 189 | #define CP_ME_RAM_DATA 0xC160 |