Commit cd404af0 authored by Michel Dänzer's avatar Michel Dänzer Committed by Alex Deucher

drm/radeon: Clean up reference counting and pinning of the cursor BOs

Take a GEM reference for and pin the new cursor BO, unpin and drop the
GEM reference for the old cursor BO in radeon_crtc_cursor_set2, and use
radeon_crtc->cursor_addr in radeon_set_cursor.

This fixes radeon_cursor_reset accidentally incrementing the cursor BO
pin count, and cleans up the code a little.

Cc: stable@vger.kernel.org
Reviewed-by: default avatarGrigori Goronzy <greg@chown.ath.cx>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarMichel Dänzer <michel.daenzer@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 866a9204
...@@ -205,8 +205,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) ...@@ -205,8 +205,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
| (x << 16) | (x << 16)
| y)); | y));
/* offset is from DISP(2)_BASE_ADDRESS */ /* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
(yorigin * 256))); radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr +
yorigin * 256);
} }
radeon_crtc->cursor_x = x; radeon_crtc->cursor_x = x;
...@@ -227,51 +228,32 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -227,51 +228,32 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
return ret; return ret;
} }
static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) static void radeon_set_cursor(struct drm_crtc *crtc)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private; struct radeon_device *rdev = crtc->dev->dev_private;
struct radeon_bo *robj = gem_to_radeon_bo(obj);
uint64_t gpu_addr;
int ret;
ret = radeon_bo_reserve(robj, false);
if (unlikely(ret != 0))
goto fail;
/* Only 27 bit offset for legacy cursor */
ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
&gpu_addr);
radeon_bo_unreserve(robj);
if (ret)
goto fail;
if (ASIC_IS_DCE4(rdev)) { if (ASIC_IS_DCE4(rdev)) {
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
upper_32_bits(gpu_addr)); upper_32_bits(radeon_crtc->cursor_addr));
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
gpu_addr & 0xffffffff); lower_32_bits(radeon_crtc->cursor_addr));
} else if (ASIC_IS_AVIVO(rdev)) { } else if (ASIC_IS_AVIVO(rdev)) {
if (rdev->family >= CHIP_RV770) { if (rdev->family >= CHIP_RV770) {
if (radeon_crtc->crtc_id) if (radeon_crtc->crtc_id)
WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH,
upper_32_bits(radeon_crtc->cursor_addr));
else else
WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH,
upper_32_bits(radeon_crtc->cursor_addr));
} }
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
gpu_addr & 0xffffffff); lower_32_bits(radeon_crtc->cursor_addr));
} else { } else {
radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
/* offset is from DISP(2)_BASE_ADDRESS */ /* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr);
} }
return 0;
fail:
drm_gem_object_unreference_unlocked(obj);
return ret;
} }
int radeon_crtc_cursor_set2(struct drm_crtc *crtc, int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
...@@ -283,7 +265,9 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ...@@ -283,7 +265,9 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
int32_t hot_y) int32_t hot_y)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct radeon_bo *robj;
int ret; int ret;
if (!handle) { if (!handle) {
...@@ -305,6 +289,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ...@@ -305,6 +289,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
return -ENOENT; return -ENOENT;
} }
robj = gem_to_radeon_bo(obj);
ret = radeon_bo_reserve(robj, false);
if (ret != 0) {
drm_gem_object_unreference_unlocked(obj);
return ret;
}
/* Only 27 bit offset for legacy cursor */
ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
&radeon_crtc->cursor_addr);
radeon_bo_unreserve(robj);
if (ret) {
DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
drm_gem_object_unreference_unlocked(obj);
return ret;
}
radeon_crtc->cursor_width = width; radeon_crtc->cursor_width = width;
radeon_crtc->cursor_height = height; radeon_crtc->cursor_height = height;
...@@ -323,13 +324,8 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ...@@ -323,13 +324,8 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
radeon_crtc->cursor_hot_y = hot_y; radeon_crtc->cursor_hot_y = hot_y;
} }
ret = radeon_set_cursor(crtc, obj); radeon_set_cursor(crtc);
radeon_show_cursor(crtc);
if (ret)
DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n",
ret);
else
radeon_show_cursor(crtc);
radeon_lock_cursor(crtc, false); radeon_lock_cursor(crtc, false);
...@@ -341,8 +337,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ...@@ -341,8 +337,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
radeon_bo_unpin(robj); radeon_bo_unpin(robj);
radeon_bo_unreserve(robj); radeon_bo_unreserve(robj);
} }
if (radeon_crtc->cursor_bo != obj) drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo);
drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo);
} }
radeon_crtc->cursor_bo = obj; radeon_crtc->cursor_bo = obj;
...@@ -360,7 +355,6 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, ...@@ -360,7 +355,6 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
void radeon_cursor_reset(struct drm_crtc *crtc) void radeon_cursor_reset(struct drm_crtc *crtc)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
int ret;
if (radeon_crtc->cursor_bo) { if (radeon_crtc->cursor_bo) {
radeon_lock_cursor(crtc, true); radeon_lock_cursor(crtc, true);
...@@ -368,12 +362,8 @@ void radeon_cursor_reset(struct drm_crtc *crtc) ...@@ -368,12 +362,8 @@ void radeon_cursor_reset(struct drm_crtc *crtc)
radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x,
radeon_crtc->cursor_y); radeon_crtc->cursor_y);
ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); radeon_set_cursor(crtc);
if (ret) radeon_show_cursor(crtc);
DRM_ERROR("radeon_set_cursor returned %d, not showing "
"cursor\n", ret);
else
radeon_show_cursor(crtc);
radeon_lock_cursor(crtc, false); radeon_lock_cursor(crtc, false);
} }
......
...@@ -343,7 +343,6 @@ struct radeon_crtc { ...@@ -343,7 +343,6 @@ struct radeon_crtc {
int max_cursor_width; int max_cursor_width;
int max_cursor_height; int max_cursor_height;
uint32_t legacy_display_base_addr; uint32_t legacy_display_base_addr;
uint32_t legacy_cursor_offset;
enum radeon_rmx_type rmx_type; enum radeon_rmx_type rmx_type;
u8 h_border; u8 h_border;
u8 v_border; u8 v_border;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment