mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-25 10:19:47 +00:00
- Allow fb changes in async commits (fixes igt failures) (Helen)
- Actually unmap the scatterlist when unmapping udmabuf (Lucas) Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Helen Koike <helen.koike@collabora.com> -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEfxcpfMSgdnQMs+QqlvcN/ahKBwoFAlz4JUkACgkQlvcN/ahK BwoyBAf/d1zGIzbAqC4j/IQIfRfCgKvo7tBpO91GgiicX7ZtjILVzgmbm8HjJ9VC ipEE6gdzewnZcY8n0V35c8a95Y9hJsXzDybMxBlLIlo6MzXQK4jlAqv8W4r3E2Q/ QAJYb0O9QBdlqWzk+UIvIxUkah4d1A1c5HlI4gETetObC6dBSBsCkKV54Hl1JjAe +RDHJHN2cSxxK/QEjwYvMDun5HmodlwetDNXVIftAseaZHrm7Dveu8PeENTuk5d3 t4F2jxQNDHuX5cRphQqBmcnUMFaig/jdlZ8GpuaZfHTZojwucmTPw8xknCHY2OeG HgBdUpVkLRHUgK7xJu3PkddjtZUT+A== =7fpu -----END PGP SIGNATURE----- Merge tag 'drm-misc-fixes-2019-06-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes - Allow fb changes in async commits (fixes igt failures) (Helen) - Actually unmap the scatterlist when unmapping udmabuf (Lucas) Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Helen Koike <helen.koike@collabora.com> Signed-off-by: Dave Airlie <airlied@redhat.com> From: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20190605210335.GA35431@art_vandelay
This commit is contained in:
commit
dbd9f78ed2
7 changed files with 52 additions and 37 deletions
|
@ -77,6 +77,7 @@ static void unmap_udmabuf(struct dma_buf_attachment *at,
|
|||
struct sg_table *sg,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
dma_unmap_sg(at->dev, sg->sgl, sg->nents, direction);
|
||||
sg_free_table(sg);
|
||||
kfree(sg);
|
||||
}
|
||||
|
|
|
@ -4232,8 +4232,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
|
|||
struct drm_plane_state *old_state =
|
||||
drm_atomic_get_old_plane_state(new_state->state, plane);
|
||||
|
||||
if (plane->state->fb != new_state->fb)
|
||||
drm_atomic_set_fb_for_plane(plane->state, new_state->fb);
|
||||
swap(plane->state->fb, new_state->fb);
|
||||
|
||||
plane->state->src_x = new_state->src_x;
|
||||
plane->state->src_y = new_state->src_y;
|
||||
|
|
|
@ -1607,15 +1607,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
|
|||
old_plane_state->crtc != new_plane_state->crtc)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* FIXME: Since prepare_fb and cleanup_fb are always called on
|
||||
* the new_plane_state for async updates we need to block framebuffer
|
||||
* changes. This prevents use of a fb that's been cleaned up and
|
||||
* double cleanups from occuring.
|
||||
*/
|
||||
if (old_plane_state->fb != new_plane_state->fb)
|
||||
return -EINVAL;
|
||||
|
||||
funcs = plane->helper_private;
|
||||
if (!funcs->atomic_async_update)
|
||||
return -EINVAL;
|
||||
|
@ -1646,6 +1637,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check);
|
|||
* drm_atomic_async_check() succeeds. Async commits are not supposed to swap
|
||||
* the states like normal sync commits, but just do in-place changes on the
|
||||
* current state.
|
||||
*
|
||||
* TODO: Implement full swap instead of doing in-place changes.
|
||||
*/
|
||||
void drm_atomic_helper_async_commit(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
|
@ -1656,6 +1649,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
|
|||
int i;
|
||||
|
||||
for_each_new_plane_in_state(state, plane, plane_state, i) {
|
||||
struct drm_framebuffer *new_fb = plane_state->fb;
|
||||
struct drm_framebuffer *old_fb = plane->state->fb;
|
||||
|
||||
funcs = plane->helper_private;
|
||||
funcs->atomic_async_update(plane, plane_state);
|
||||
|
||||
|
@ -1664,11 +1660,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
|
|||
* plane->state in-place, make sure at least common
|
||||
* properties have been properly updated.
|
||||
*/
|
||||
WARN_ON_ONCE(plane->state->fb != plane_state->fb);
|
||||
WARN_ON_ONCE(plane->state->fb != new_fb);
|
||||
WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x);
|
||||
WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y);
|
||||
WARN_ON_ONCE(plane->state->src_x != plane_state->src_x);
|
||||
WARN_ON_ONCE(plane->state->src_y != plane_state->src_y);
|
||||
|
||||
/*
|
||||
* Make sure the FBs have been swapped so that cleanups in the
|
||||
* new_state performs a cleanup in the old FB.
|
||||
*/
|
||||
WARN_ON_ONCE(plane_state->fb != old_fb);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_async_commit);
|
||||
|
|
|
@ -502,6 +502,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
|
|||
static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct drm_framebuffer *old_fb = plane->state->fb;
|
||||
|
||||
plane->state->src_x = new_state->src_x;
|
||||
plane->state->src_y = new_state->src_y;
|
||||
plane->state->crtc_x = new_state->crtc_x;
|
||||
|
@ -524,6 +526,8 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
|
|||
|
||||
*to_mdp5_plane_state(plane->state) =
|
||||
*to_mdp5_plane_state(new_state);
|
||||
|
||||
new_state->fb = old_fb;
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
|
||||
|
|
|
@ -924,29 +924,17 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
|
|||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct vop *vop = to_vop(plane->state->crtc);
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_framebuffer *old_fb = plane->state->fb;
|
||||
|
||||
plane_state = plane->funcs->atomic_duplicate_state(plane);
|
||||
plane_state->crtc_x = new_state->crtc_x;
|
||||
plane_state->crtc_y = new_state->crtc_y;
|
||||
plane_state->crtc_h = new_state->crtc_h;
|
||||
plane_state->crtc_w = new_state->crtc_w;
|
||||
plane_state->src_x = new_state->src_x;
|
||||
plane_state->src_y = new_state->src_y;
|
||||
plane_state->src_h = new_state->src_h;
|
||||
plane_state->src_w = new_state->src_w;
|
||||
|
||||
if (plane_state->fb != new_state->fb)
|
||||
drm_atomic_set_fb_for_plane(plane_state, new_state->fb);
|
||||
|
||||
swap(plane_state, plane->state);
|
||||
|
||||
if (plane->state->fb && plane->state->fb != new_state->fb) {
|
||||
drm_framebuffer_get(plane->state->fb);
|
||||
WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
|
||||
drm_flip_work_queue(&vop->fb_unref_work, plane->state->fb);
|
||||
set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
|
||||
}
|
||||
plane->state->crtc_x = new_state->crtc_x;
|
||||
plane->state->crtc_y = new_state->crtc_y;
|
||||
plane->state->crtc_h = new_state->crtc_h;
|
||||
plane->state->crtc_w = new_state->crtc_w;
|
||||
plane->state->src_x = new_state->src_x;
|
||||
plane->state->src_y = new_state->src_y;
|
||||
plane->state->src_h = new_state->src_h;
|
||||
plane->state->src_w = new_state->src_w;
|
||||
swap(plane->state->fb, new_state->fb);
|
||||
|
||||
if (vop->is_enabled) {
|
||||
rockchip_drm_psr_inhibit_get_state(new_state->state);
|
||||
|
@ -955,9 +943,22 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
|
|||
vop_cfg_done(vop);
|
||||
spin_unlock(&vop->reg_lock);
|
||||
rockchip_drm_psr_inhibit_put_state(new_state->state);
|
||||
}
|
||||
|
||||
plane->funcs->atomic_destroy_state(plane, plane_state);
|
||||
/*
|
||||
* A scanout can still be occurring, so we can't drop the
|
||||
* reference to the old framebuffer. To solve this we get a
|
||||
* reference to old_fb and set a worker to release it later.
|
||||
* FIXME: if we perform 500 async_update calls before the
|
||||
* vblank, then we can have 500 different framebuffers waiting
|
||||
* to be released.
|
||||
*/
|
||||
if (old_fb && plane->state->fb != old_fb) {
|
||||
drm_framebuffer_get(old_fb);
|
||||
WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
|
||||
drm_flip_work_queue(&vop->fb_unref_work, old_fb);
|
||||
set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs plane_helper_funcs = {
|
||||
|
|
|
@ -1025,7 +1025,7 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
|
|||
{
|
||||
struct vc4_plane_state *vc4_state, *new_vc4_state;
|
||||
|
||||
drm_atomic_set_fb_for_plane(plane->state, state->fb);
|
||||
swap(plane->state->fb, state->fb);
|
||||
plane->state->crtc_x = state->crtc_x;
|
||||
plane->state->crtc_y = state->crtc_y;
|
||||
plane->state->crtc_w = state->crtc_w;
|
||||
|
|
|
@ -1185,6 +1185,14 @@ struct drm_plane_helper_funcs {
|
|||
* current one with the new plane configurations in the new
|
||||
* plane_state.
|
||||
*
|
||||
* Drivers should also swap the framebuffers between current plane
|
||||
* state (&drm_plane.state) and new_state.
|
||||
* This is required since cleanup for async commits is performed on
|
||||
* the new state, rather than old state like for traditional commits.
|
||||
* Since we want to give up the reference on the current (old) fb
|
||||
* instead of our brand new one, swap them in the driver during the
|
||||
* async commit.
|
||||
*
|
||||
* FIXME:
|
||||
* - It only works for single plane updates
|
||||
* - Async Pageflips are not supported yet
|
||||
|
|
Loading…
Reference in a new issue