drm/radeon: Restrict offset for legacy hardware cursor.
authorMichel Dänzer <michel.daenzer@amd.com>
Wed, 14 Mar 2012 16:12:41 +0000 (17:12 +0100)
committerDave Airlie <airlied@redhat.com>
Tue, 20 Mar 2012 08:47:41 +0000 (08:47 +0000)
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>
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_object.h

index fde25c0d65a043427fecb143ec6c4603e708d27c..986d608002a36b60ef543d81e84bfe625032964f 100644 (file)
@@ -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);
index 342deaccc152607d9ce46654022e1b141059bfeb..91541e63d582706416b8bba9365c4930c6dadf29 100644 (file)
@@ -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;
index cde430308870f75247aa5901320731a0a917ceb2..f9104be88d7c12e48ec92254109ec6991b9e725e 100644 (file)
@@ -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);