[PATCH 1/2] drm/radeon: Restrict offset for legacy hardware cursor.

Alex Deucher alexdeucher at gmail.com
Wed Mar 14 08:08:42 PDT 2012


2012/3/14 Michel Dänzer <michel at daenzer.net>:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> 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 at vger.kernel.org
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list