aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon/ni.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/ni.c')
-rw-r--r--drivers/gpu/drm/radeon/ni.c198
1 files changed, 95 insertions, 103 deletions
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index b7bf18e4021..9945d86d900 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -850,11 +850,20 @@ void cayman_fence_ring_emit(struct radeon_device *rdev,
void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{
- struct radeon_ring *ring = &rdev->ring[ib->fence->ring];
+ struct radeon_ring *ring = &rdev->ring[ib->ring];
/* set to DX10/11 mode */
radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
radeon_ring_write(ring, 1);
+
+ if (ring->rptr_save_reg) {
+ uint32_t next_rptr = ring->wptr + 3 + 4 + 8;
+ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+ radeon_ring_write(ring, ((ring->rptr_save_reg -
+ PACKET3_SET_CONFIG_REG_START) >> 2));
+ radeon_ring_write(ring, next_rptr);
+ }
+
radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
radeon_ring_write(ring,
#ifdef __BIG_ENDIAN
@@ -981,16 +990,41 @@ static int cayman_cp_start(struct radeon_device *rdev)
static void cayman_cp_fini(struct radeon_device *rdev)
{
+ struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
cayman_cp_enable(rdev, false);
- radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
+ radeon_ring_fini(rdev, ring);
+ radeon_scratch_free(rdev, ring->rptr_save_reg);
}
int cayman_cp_resume(struct radeon_device *rdev)
{
+ static const int ridx[] = {
+ RADEON_RING_TYPE_GFX_INDEX,
+ CAYMAN_RING_TYPE_CP1_INDEX,
+ CAYMAN_RING_TYPE_CP2_INDEX
+ };
+ static const unsigned cp_rb_cntl[] = {
+ CP_RB0_CNTL,
+ CP_RB1_CNTL,
+ CP_RB2_CNTL,
+ };
+ static const unsigned cp_rb_rptr_addr[] = {
+ CP_RB0_RPTR_ADDR,
+ CP_RB1_RPTR_ADDR,
+ CP_RB2_RPTR_ADDR
+ };
+ static const unsigned cp_rb_rptr_addr_hi[] = {
+ CP_RB0_RPTR_ADDR_HI,
+ CP_RB1_RPTR_ADDR_HI,
+ CP_RB2_RPTR_ADDR_HI
+ };
+ static const unsigned cp_rb_base[] = {
+ CP_RB0_BASE,
+ CP_RB1_BASE,
+ CP_RB2_BASE
+ };
struct radeon_ring *ring;
- u32 tmp;
- u32 rb_bufsz;
- int r;
+ int i, r;
/* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */
WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP |
@@ -1012,91 +1046,47 @@ int cayman_cp_resume(struct radeon_device *rdev)
WREG32(CP_DEBUG, (1 << 27));
- /* ring 0 - compute and gfx */
- /* Set ring buffer size */
- ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
- rb_bufsz = drm_order(ring->ring_size / 8);
- tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
-#ifdef __BIG_ENDIAN
- tmp |= BUF_SWAP_32BIT;
-#endif
- WREG32(CP_RB0_CNTL, tmp);
-
- /* Initialize the ring buffer's read and write pointers */
- WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
- ring->wptr = 0;
- WREG32(CP_RB0_WPTR, ring->wptr);
-
/* set the wb address wether it's enabled or not */
- WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
- WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
+ WREG32(SCRATCH_UMSK, 0xff);
- if (rdev->wb.enabled)
- WREG32(SCRATCH_UMSK, 0xff);
- else {
- tmp |= RB_NO_UPDATE;
- WREG32(SCRATCH_UMSK, 0);
- }
+ for (i = 0; i < 3; ++i) {
+ uint32_t rb_cntl;
+ uint64_t addr;
- mdelay(1);
- WREG32(CP_RB0_CNTL, tmp);
-
- WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
-
- ring->rptr = RREG32(CP_RB0_RPTR);
-
- /* ring1 - compute only */
- /* Set ring buffer size */
- ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
- rb_bufsz = drm_order(ring->ring_size / 8);
- tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+ /* Set ring buffer size */
+ ring = &rdev->ring[ridx[i]];
+ rb_cntl = drm_order(ring->ring_size / 8);
+ rb_cntl |= drm_order(RADEON_GPU_PAGE_SIZE/8) << 8;
#ifdef __BIG_ENDIAN
- tmp |= BUF_SWAP_32BIT;
+ rb_cntl |= BUF_SWAP_32BIT;
#endif
- WREG32(CP_RB1_CNTL, tmp);
-
- /* Initialize the ring buffer's read and write pointers */
- WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
- ring->wptr = 0;
- WREG32(CP_RB1_WPTR, ring->wptr);
-
- /* set the wb address wether it's enabled or not */
- WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
- WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
-
- mdelay(1);
- WREG32(CP_RB1_CNTL, tmp);
+ WREG32(cp_rb_cntl[i], rb_cntl);
- WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
-
- ring->rptr = RREG32(CP_RB1_RPTR);
-
- /* ring2 - compute only */
- /* Set ring buffer size */
- ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
- rb_bufsz = drm_order(ring->ring_size / 8);
- tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
-#ifdef __BIG_ENDIAN
- tmp |= BUF_SWAP_32BIT;
-#endif
- WREG32(CP_RB2_CNTL, tmp);
-
- /* Initialize the ring buffer's read and write pointers */
- WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
- ring->wptr = 0;
- WREG32(CP_RB2_WPTR, ring->wptr);
+ /* set the wb address wether it's enabled or not */
+ addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET;
+ WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC);
+ WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF);
+ }
- /* set the wb address wether it's enabled or not */
- WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
- WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
+ /* set the rb base addr, this causes an internal reset of ALL rings */
+ for (i = 0; i < 3; ++i) {
+ ring = &rdev->ring[ridx[i]];
+ WREG32(cp_rb_base[i], ring->gpu_addr >> 8);
+ }
- mdelay(1);
- WREG32(CP_RB2_CNTL, tmp);
+ for (i = 0; i < 3; ++i) {
+ /* Initialize the ring buffer's read and write pointers */
+ ring = &rdev->ring[ridx[i]];
+ WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
- WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
+ ring->rptr = ring->wptr = 0;
+ WREG32(ring->rptr_reg, ring->rptr);
+ WREG32(ring->wptr_reg, ring->wptr);
- ring->rptr = RREG32(CP_RB2_RPTR);
+ mdelay(1);
+ WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
+ }
/* start the rings */
cayman_cp_start(rdev);
@@ -1132,6 +1122,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
RREG32(GRBM_STATUS_SE1));
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n",
RREG32(SRBM_STATUS));
+ dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n",
+ RREG32(CP_STALLED_STAT1));
+ dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n",
+ RREG32(CP_STALLED_STAT2));
+ dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n",
+ RREG32(CP_BUSY_STAT));
+ dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n",
+ RREG32(CP_STAT));
dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n",
RREG32(0x14F8));
dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n",
@@ -1180,6 +1178,14 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev)
RREG32(GRBM_STATUS_SE1));
dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n",
RREG32(SRBM_STATUS));
+ dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n",
+ RREG32(CP_STALLED_STAT1));
+ dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n",
+ RREG32(CP_STALLED_STAT2));
+ dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n",
+ RREG32(CP_BUSY_STAT));
+ dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n",
+ RREG32(CP_STAT));
evergreen_mc_resume(rdev, &save);
return 0;
}
@@ -1291,17 +1297,17 @@ static int cayman_startup(struct radeon_device *rdev)
if (r)
return r;
- r = radeon_ib_pool_start(rdev);
- if (r)
- return r;
-
- r = radeon_ib_ring_tests(rdev);
- if (r)
+ r = radeon_ib_pool_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
return r;
+ }
- r = radeon_vm_manager_start(rdev);
- if (r)
+ r = radeon_vm_manager_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r);
return r;
+ }
r = r600_audio_init(rdev);
if (r)
@@ -1334,10 +1340,6 @@ int cayman_resume(struct radeon_device *rdev)
int cayman_suspend(struct radeon_device *rdev)
{
r600_audio_fini(rdev);
- /* FIXME: we should wait for ring to be empty */
- radeon_ib_pool_suspend(rdev);
- radeon_vm_manager_suspend(rdev);
- r600_blit_suspend(rdev);
cayman_cp_enable(rdev, false);
rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
evergreen_irq_suspend(rdev);
@@ -1413,17 +1415,7 @@ int cayman_init(struct radeon_device *rdev)
if (r)
return r;
- r = radeon_ib_pool_init(rdev);
rdev->accel_working = true;
- if (r) {
- dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
- rdev->accel_working = false;
- }
- r = radeon_vm_manager_init(rdev);
- if (r) {
- dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r);
- }
-
r = cayman_startup(rdev);
if (r) {
dev_err(rdev->dev, "disabling GPU acceleration\n");
@@ -1432,7 +1424,7 @@ int cayman_init(struct radeon_device *rdev)
if (rdev->flags & RADEON_IS_IGP)
si_rlc_fini(rdev);
radeon_wb_fini(rdev);
- r100_ib_fini(rdev);
+ radeon_ib_pool_fini(rdev);
radeon_vm_manager_fini(rdev);
radeon_irq_kms_fini(rdev);
cayman_pcie_gart_fini(rdev);
@@ -1463,7 +1455,7 @@ void cayman_fini(struct radeon_device *rdev)
si_rlc_fini(rdev);
radeon_wb_fini(rdev);
radeon_vm_manager_fini(rdev);
- r100_ib_fini(rdev);
+ radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev);
cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);