2012/3/14 Michel Dänzer <michel@xxxxxxxxxxx>: > From: Michel Dänzer <michel.daenzer@xxxxxxx> > > 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@xxxxxxxxxxxxxxx > Signed-off-by: Michel Dänzer <michel.daenzer@xxxxxxx> Reviewed-by: Alex Deucher <alexander.deucher@xxxxxxx> FWIW, I think we may need a similar fix for the crtc base addresses. They are also limited to 27 bit offsets from the mc address specified in DISPLAY[2]_BASE_ADDR. > --- > drivers/gpu/drm/radeon/radeon_cursor.c | 13 +++++++++++-- > drivers/gpu/drm/radeon/radeon_object.c | 18 +++++++++++++++++- > drivers/gpu/drm/radeon/radeon_object.h | 2 ++ > 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 fde25c0..986d608 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, > 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); > diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c > index d45df17..388be34 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) > *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) { > + if (lpfn < bo->placement.lpfn) > + bo->placement.lpfn = lpfn; > + } else > + 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; > diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h > index cde4303..f9104be 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); > 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); > -- > 1.7.9.1 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel