Skip to content

Commit

Permalink
drm/radeon: Don't read from CP ring write pointer registers.
Browse files Browse the repository at this point in the history
Apparently this doesn't always work reliably, e.g. at resume time.

Just initialize to 0, so the ring is considered empty.

Tested with hibernation on Sumo and Cayman cards.

Should fix https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/ .

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
cc: stable@kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Michel Dänzer authored and Dave Airlie committed Sep 14, 2011
1 parent ff02b13 commit 87463ff
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 14 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/radeon/evergreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,7 +1404,8 @@ int evergreen_cp_resume(struct radeon_device *rdev)
/* Initialize the ring buffer's read and write pointers */
WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA);
WREG32(CP_RB_RPTR_WR, 0);
WREG32(CP_RB_WPTR, 0);
rdev->cp.wptr = 0;
WREG32(CP_RB_WPTR, rdev->cp.wptr);

/* set the wb address wether it's enabled or not */
WREG32(CP_RB_RPTR_ADDR,
Expand All @@ -1426,7 +1427,6 @@ int evergreen_cp_resume(struct radeon_device *rdev)
WREG32(CP_DEBUG, (1 << 27) | (1 << 28));

rdev->cp.rptr = RREG32(CP_RB_RPTR);
rdev->cp.wptr = RREG32(CP_RB_WPTR);

evergreen_cp_start(rdev);
rdev->cp.ready = true;
Expand Down
12 changes: 6 additions & 6 deletions drivers/gpu/drm/radeon/ni.c
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,8 @@ int cayman_cp_resume(struct radeon_device *rdev)

/* Initialize the ring buffer's read and write pointers */
WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
WREG32(CP_RB0_WPTR, 0);
rdev->cp.wptr = 0;
WREG32(CP_RB0_WPTR, rdev->cp.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);
Expand All @@ -1207,7 +1208,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8);

rdev->cp.rptr = RREG32(CP_RB0_RPTR);
rdev->cp.wptr = RREG32(CP_RB0_WPTR);

/* ring1 - compute only */
/* Set ring buffer size */
Expand All @@ -1220,7 +1220,8 @@ int cayman_cp_resume(struct radeon_device *rdev)

/* Initialize the ring buffer's read and write pointers */
WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
WREG32(CP_RB1_WPTR, 0);
rdev->cp1.wptr = 0;
WREG32(CP_RB1_WPTR, rdev->cp1.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);
Expand All @@ -1232,7 +1233,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8);

rdev->cp1.rptr = RREG32(CP_RB1_RPTR);
rdev->cp1.wptr = RREG32(CP_RB1_WPTR);

/* ring2 - compute only */
/* Set ring buffer size */
Expand All @@ -1245,7 +1245,8 @@ int cayman_cp_resume(struct radeon_device *rdev)

/* Initialize the ring buffer's read and write pointers */
WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
WREG32(CP_RB2_WPTR, 0);
rdev->cp2.wptr = 0;
WREG32(CP_RB2_WPTR, rdev->cp2.wptr);

/* 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);
Expand All @@ -1257,7 +1258,6 @@ int cayman_cp_resume(struct radeon_device *rdev)
WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8);

rdev->cp2.rptr = RREG32(CP_RB2_RPTR);
rdev->cp2.wptr = RREG32(CP_RB2_WPTR);

/* start the rings */
cayman_cp_start(rdev);
Expand Down
6 changes: 2 additions & 4 deletions drivers/gpu/drm/radeon/r100.c
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
/* Force read & write ptr to 0 */
WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE);
WREG32(RADEON_CP_RB_RPTR_WR, 0);
WREG32(RADEON_CP_RB_WPTR, 0);
rdev->cp.wptr = 0;
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);

/* set the wb address whether it's enabled or not */
WREG32(R_00070C_CP_RB_RPTR_ADDR,
Expand All @@ -1007,9 +1008,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
WREG32(RADEON_CP_RB_CNTL, tmp);
udelay(10);
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR);
/* protect against crazy HW on resume */
rdev->cp.wptr &= rdev->cp.ptr_mask;
/* Set cp mode to bus mastering & enable cp*/
WREG32(RADEON_CP_CSQ_MODE,
REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/radeon/r600.c
Original file line number Diff line number Diff line change
Expand Up @@ -2209,7 +2209,8 @@ int r600_cp_resume(struct radeon_device *rdev)
/* Initialize the ring buffer's read and write pointers */
WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA);
WREG32(CP_RB_RPTR_WR, 0);
WREG32(CP_RB_WPTR, 0);
rdev->cp.wptr = 0;
WREG32(CP_RB_WPTR, rdev->cp.wptr);

/* set the wb address whether it's enabled or not */
WREG32(CP_RB_RPTR_ADDR,
Expand All @@ -2231,7 +2232,6 @@ int r600_cp_resume(struct radeon_device *rdev)
WREG32(CP_DEBUG, (1 << 27) | (1 << 28));

rdev->cp.rptr = RREG32(CP_RB_RPTR);
rdev->cp.wptr = RREG32(CP_RB_WPTR);

r600_cp_start(rdev);
rdev->cp.ready = true;
Expand Down

0 comments on commit 87463ff

Please sign in to comment.