Commit c4353016 authored by Michel Dänzer's avatar Michel Dänzer Committed by Dave Airlie

drm/radeon: Restrict offset for legacy hardware cursor.

The hardware only takes 27 bits for the offset, so larger offsets are
truncated, and the hardware cursor shows random bits other than the intended
ones.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=46796

Cc: stable@vger.kernel.org
Signed-off-by: default avatarMichel Dänzer <michel.daenzer@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 11fe1266
...@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t height) uint32_t height)
{ {
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;
uint64_t gpu_addr; uint64_t gpu_addr;
int ret; int ret;
...@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT; return -ENOENT;
} }
ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); robj = gem_to_radeon_bo(obj);
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) if (ret)
goto fail; goto fail;
...@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
radeon_crtc->cursor_height = height; radeon_crtc->cursor_height = height;
radeon_lock_cursor(crtc, true); radeon_lock_cursor(crtc, true);
/* XXX only 27 bit offset for legacy cursor */
radeon_set_cursor(crtc, obj, gpu_addr); radeon_set_cursor(crtc, obj, gpu_addr);
radeon_show_cursor(crtc); radeon_show_cursor(crtc);
radeon_lock_cursor(crtc, false); radeon_lock_cursor(crtc, false);
......
...@@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **bo) ...@@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **bo)
*bo = NULL; *bo = NULL;
} }
int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
u64 *gpu_addr)
{ {
int r, i; int r, i;
...@@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) ...@@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
bo->pin_count++; bo->pin_count++;
if (gpu_addr) if (gpu_addr)
*gpu_addr = radeon_bo_gpu_offset(bo); *gpu_addr = radeon_bo_gpu_offset(bo);
WARN_ON_ONCE(max_offset != 0);
return 0; return 0;
} }
radeon_ttm_placement_from_domain(bo, domain); radeon_ttm_placement_from_domain(bo, domain);
...@@ -239,6 +241,15 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) ...@@ -239,6 +241,15 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
/* force to pin into visible video ram */ /* force to pin into visible video ram */
bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT; bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
} }
if (max_offset) {
u64 lpfn = max_offset >> PAGE_SHIFT;
if (!bo->placement.lpfn)
bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
if (lpfn < bo->placement.lpfn)
bo->placement.lpfn = lpfn;
}
for (i = 0; i < bo->placement.num_placement; i++) for (i = 0; i < bo->placement.num_placement; i++)
bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false); r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
...@@ -252,6 +263,11 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) ...@@ -252,6 +263,11 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
return r; return r;
} }
int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
{
return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
}
int radeon_bo_unpin(struct radeon_bo *bo) int radeon_bo_unpin(struct radeon_bo *bo)
{ {
int r, i; int r, i;
......
...@@ -118,6 +118,8 @@ extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); ...@@ -118,6 +118,8 @@ extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
extern void radeon_bo_kunmap(struct radeon_bo *bo); extern void radeon_bo_kunmap(struct radeon_bo *bo);
extern void radeon_bo_unref(struct radeon_bo **bo); extern void radeon_bo_unref(struct radeon_bo **bo);
extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr); extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
u64 max_offset, u64 *gpu_addr);
extern int radeon_bo_unpin(struct radeon_bo *bo); extern int radeon_bo_unpin(struct radeon_bo *bo);
extern int radeon_bo_evict_vram(struct radeon_device *rdev); extern int radeon_bo_evict_vram(struct radeon_device *rdev);
extern void radeon_bo_force_delete(struct radeon_device *rdev); extern void radeon_bo_force_delete(struct radeon_device *rdev);
......
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