Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
			   uint32_t height)
{
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
	struct radeon_device *rdev = crtc->dev->dev_private;
	struct drm_gem_object *obj;
	struct radeon_bo *robj;
	uint64_t gpu_addr;
	int ret;

@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
		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)
		goto fail;

@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
	radeon_crtc->cursor_height = height;

	radeon_lock_cursor(crtc, true);
	/* XXX only 27 bit offset for legacy cursor */
	radeon_set_cursor(crtc, obj, gpu_addr);
	radeon_show_cursor(crtc);
	radeon_lock_cursor(crtc, false);
+17 −1
Original line number Diff line number Diff line
@@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **bo)
		*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;

@@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
		bo->pin_count++;
		if (gpu_addr)
			*gpu_addr = radeon_bo_gpu_offset(bo);
		WARN_ON_ONCE(max_offset != 0);
		return 0;
	}
	radeon_ttm_placement_from_domain(bo, domain);
@@ -239,6 +241,15 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
		/* force to pin into visible video ram */
		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++)
		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
	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)
	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 r, i;
+2 −0
Original line number Diff line number Diff line
@@ -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_unref(struct radeon_bo **bo);
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_evict_vram(struct radeon_device *rdev);
extern void radeon_bo_force_delete(struct radeon_device *rdev);