> -----Original Message----- > From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf > Of Michel Dänzer > Sent: Thursday, October 27, 2016 4:00 AM > To: amd-gfx at lists.freedesktop.org > Cc: Takashi Iwai; Tomáš Chvátal > Subject: [PATCH 3/3] drm/radeon: Hide the HW cursor while it's out of > bounds > > From: Michel Dänzer <michel.daenzer at amd.com> > > Fixes hangs in that case under some circumstances. > > Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000433 > Cc: stable at vger.kernel.org > Signed-off-by: Michel Dänzer <michel.daenzer at amd.com> For the series: Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > --- > drivers/gpu/drm/radeon/radeon_cursor.c | 66 +++++++++++++++++++++-- > ----------- > drivers/gpu/drm/radeon/radeon_mode.h | 1 + > 2 files changed, 42 insertions(+), 25 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c > b/drivers/gpu/drm/radeon/radeon_cursor.c > index a3405fc..baf632a 100644 > --- a/drivers/gpu/drm/radeon/radeon_cursor.c > +++ b/drivers/gpu/drm/radeon/radeon_cursor.c > @@ -90,6 +90,9 @@ static void radeon_show_cursor(struct drm_crtc *crtc) > struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); > struct radeon_device *rdev = crtc->dev->dev_private; > > + if (radeon_crtc->cursor_out_of_bounds) > + return; > + > if (ASIC_IS_DCE4(rdev)) { > WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + > radeon_crtc->crtc_offset, > upper_32_bits(radeon_crtc->cursor_addr)); > @@ -146,21 +149,14 @@ static int radeon_cursor_move_locked(struct > drm_crtc *crtc, int x, int y) > radeon_crtc->cursor_x = x; > radeon_crtc->cursor_y = y; > > - if (ASIC_IS_AVIVO(rdev)) { > - /* avivo cursor are offset into the total surface */ > - x += crtc->x; > - y += crtc->y; > - } > - DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); > - > - if (x < 0) { > + if (x < 0) > xorigin = min(-x, radeon_crtc->max_cursor_width - 1); > - x = 0; > - } > - if (y < 0) { > + if (y < 0) > yorigin = min(-y, radeon_crtc->max_cursor_height - 1); > - y = 0; > - } > + > + x += crtc->x; > + y += crtc->y; > + DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); > > /* fixed on DCE6 and newer */ > if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { > @@ -183,27 +179,31 @@ static int radeon_cursor_move_locked(struct > drm_crtc *crtc, int x, int y) > if (i > 1) { > int cursor_end, frame_end; > > - cursor_end = x - xorigin + w; > + cursor_end = x + w; > frame_end = crtc->x + crtc->mode.crtc_hdisplay; > if (cursor_end >= frame_end) { > w = w - (cursor_end - frame_end); > if (!(frame_end & 0x7f)) > w--; > - } else { > - if (!(cursor_end & 0x7f)) > - w--; > + } else if (cursor_end <= 0) { > + goto out_of_bounds; > + } else if (!(cursor_end & 0x7f)) { > + w--; > } > if (w <= 0) { > - w = 1; > - cursor_end = x - xorigin + w; > - if (!(cursor_end & 0x7f)) { > - x--; > - WARN_ON_ONCE(x < 0); > - } > + goto out_of_bounds; > } > } > } > > + if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) || > + x >= (crtc->x + crtc->mode.crtc_hdisplay) || > + y >= (crtc->y + crtc->mode.crtc_vdisplay)) > + goto out_of_bounds; > + > + x += xorigin; > + y += yorigin; > + > if (ASIC_IS_DCE4(rdev)) { > WREG32(EVERGREEN_CUR_POSITION + radeon_crtc- > >crtc_offset, (x << 16) | y); > WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc- > >crtc_offset, (xorigin << 16) | yorigin); > @@ -215,6 +215,9 @@ static int radeon_cursor_move_locked(struct > drm_crtc *crtc, int x, int y) > WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, > ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); > } else { > + x -= crtc->x; > + y -= crtc->y; > + > if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) > y *= 2; > > @@ -232,6 +235,19 @@ static int radeon_cursor_move_locked(struct > drm_crtc *crtc, int x, int y) > yorigin * 256); > } > > + if (radeon_crtc->cursor_out_of_bounds) { > + radeon_crtc->cursor_out_of_bounds = false; > + if (radeon_crtc->cursor_bo) > + radeon_show_cursor(crtc); > + } > + > + return 0; > + > + out_of_bounds: > + if (!radeon_crtc->cursor_out_of_bounds) { > + radeon_hide_cursor(crtc); > + radeon_crtc->cursor_out_of_bounds = true; > + } > return 0; > } > > @@ -308,12 +324,12 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, > x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - > hot_x; > y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - > hot_y; > > - radeon_cursor_move_locked(crtc, x, y); > - > radeon_crtc->cursor_width = width; > radeon_crtc->cursor_height = height; > radeon_crtc->cursor_hot_x = hot_x; > radeon_crtc->cursor_hot_y = hot_y; > + > + radeon_cursor_move_locked(crtc, x, y); > } > > radeon_show_cursor(crtc); > diff --git a/drivers/gpu/drm/radeon/radeon_mode.h > b/drivers/gpu/drm/radeon/radeon_mode.h > index bb75201a..f1da484 100644 > --- a/drivers/gpu/drm/radeon/radeon_mode.h > +++ b/drivers/gpu/drm/radeon/radeon_mode.h > @@ -330,6 +330,7 @@ struct radeon_crtc { > u16 lut_r[256], lut_g[256], lut_b[256]; > bool enabled; > bool can_tile; > + bool cursor_out_of_bounds; > uint32_t crtc_offset; > struct drm_gem_object *cursor_bo; > uint64_t cursor_addr; > -- > 2.10.1 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx