aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2012-03-14 12:12:41 -0400
committerDave Airlie <airlied@redhat.com>2012-03-20 04:47:41 -0400
commitc4353016dac10133fa5d8535af83f0c4845a2915 (patch)
treefce6312c5ae82648d08b651511d0be2408f21eb8
parent11fe1266253a96c4d4ac9c07918372a98248c62e (diff)
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: Michel Dänzer <michel.daenzer@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c18
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h2
3 files changed, 30 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index fde25c0d65a0..986d608002a3 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
151 uint32_t height) 151 uint32_t height)
152{ 152{
153 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 153 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
154 struct radeon_device *rdev = crtc->dev->dev_private;
154 struct drm_gem_object *obj; 155 struct drm_gem_object *obj;
156 struct radeon_bo *robj;
155 uint64_t gpu_addr; 157 uint64_t gpu_addr;
156 int ret; 158 int ret;
157 159
@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
173 return -ENOENT; 175 return -ENOENT;
174 } 176 }
175 177
176 ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); 178 robj = gem_to_radeon_bo(obj);
179 ret = radeon_bo_reserve(robj, false);
180 if (unlikely(ret != 0))
181 goto fail;
182 /* Only 27 bit offset for legacy cursor */
183 ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
184 ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
185 &gpu_addr);
186 radeon_bo_unreserve(robj);
177 if (ret) 187 if (ret)
178 goto fail; 188 goto fail;
179 189
@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
181 radeon_crtc->cursor_height = height; 191 radeon_crtc->cursor_height = height;
182 192
183 radeon_lock_cursor(crtc, true); 193 radeon_lock_cursor(crtc, true);
184 /* XXX only 27 bit offset for legacy cursor */
185 radeon_set_cursor(crtc, obj, gpu_addr); 194 radeon_set_cursor(crtc, obj, gpu_addr);
186 radeon_show_cursor(crtc); 195 radeon_show_cursor(crtc);
187 radeon_lock_cursor(crtc, false); 196 radeon_lock_cursor(crtc, false);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 342deaccc152..91541e63d582 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **bo)
224 *bo = NULL; 224 *bo = NULL;
225} 225}
226 226
227int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) 227int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
228 u64 *gpu_addr)
228{ 229{
229 int r, i; 230 int r, i;
230 231
@@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
232 bo->pin_count++; 233 bo->pin_count++;
233 if (gpu_addr) 234 if (gpu_addr)
234 *gpu_addr = radeon_bo_gpu_offset(bo); 235 *gpu_addr = radeon_bo_gpu_offset(bo);
236 WARN_ON_ONCE(max_offset != 0);
235 return 0; 237 return 0;
236 } 238 }
237 radeon_ttm_placement_from_domain(bo, domain); 239 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 /* force to pin into visible video ram */ 241 /* force to pin into visible video ram */
240 bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT; 242 bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
241 } 243 }
244 if (max_offset) {
245 u64 lpfn = max_offset >> PAGE_SHIFT;
246
247 if (!bo->placement.lpfn)
248 bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
249
250 if (lpfn < bo->placement.lpfn)
251 bo->placement.lpfn = lpfn;
252 }
242 for (i = 0; i < bo->placement.num_placement; i++) 253 for (i = 0; i < bo->placement.num_placement; i++)
243 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; 254 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
244 r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false); 255 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 return r; 263 return r;
253} 264}
254 265
266int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
267{
268 return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
269}
270
255int radeon_bo_unpin(struct radeon_bo *bo) 271int radeon_bo_unpin(struct radeon_bo *bo)
256{ 272{
257 int r, i; 273 int r, i;
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index cde430308870..f9104be88d7c 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -118,6 +118,8 @@ extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
118extern void radeon_bo_kunmap(struct radeon_bo *bo); 118extern void radeon_bo_kunmap(struct radeon_bo *bo);
119extern void radeon_bo_unref(struct radeon_bo **bo); 119extern void radeon_bo_unref(struct radeon_bo **bo);
120extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr); 120extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
121extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
122 u64 max_offset, u64 *gpu_addr);
121extern int radeon_bo_unpin(struct radeon_bo *bo); 123extern int radeon_bo_unpin(struct radeon_bo *bo);
122extern int radeon_bo_evict_vram(struct radeon_device *rdev); 124extern int radeon_bo_evict_vram(struct radeon_device *rdev);
123extern void radeon_bo_force_delete(struct radeon_device *rdev); 125extern void radeon_bo_force_delete(struct radeon_device *rdev);