Commit dbd9f78e authored by Dave Airlie's avatar Dave Airlie

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: default avatarDave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20190605210335.GA35431@art_vandelay
parents 75cb3776 283f1e38
...@@ -77,6 +77,7 @@ static void unmap_udmabuf(struct dma_buf_attachment *at, ...@@ -77,6 +77,7 @@ static void unmap_udmabuf(struct dma_buf_attachment *at,
struct sg_table *sg, struct sg_table *sg,
enum dma_data_direction direction) enum dma_data_direction direction)
{ {
dma_unmap_sg(at->dev, sg->sgl, sg->nents, direction);
sg_free_table(sg); sg_free_table(sg);
kfree(sg); kfree(sg);
} }
......
...@@ -4232,8 +4232,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane, ...@@ -4232,8 +4232,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
struct drm_plane_state *old_state = struct drm_plane_state *old_state =
drm_atomic_get_old_plane_state(new_state->state, plane); drm_atomic_get_old_plane_state(new_state->state, plane);
if (plane->state->fb != new_state->fb) swap(plane->state->fb, new_state->fb);
drm_atomic_set_fb_for_plane(plane->state, new_state->fb);
plane->state->src_x = new_state->src_x; plane->state->src_x = new_state->src_x;
plane->state->src_y = new_state->src_y; plane->state->src_y = new_state->src_y;
......
...@@ -1607,15 +1607,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev, ...@@ -1607,15 +1607,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
old_plane_state->crtc != new_plane_state->crtc) old_plane_state->crtc != new_plane_state->crtc)
return -EINVAL; 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; funcs = plane->helper_private;
if (!funcs->atomic_async_update) if (!funcs->atomic_async_update)
return -EINVAL; return -EINVAL;
...@@ -1646,6 +1637,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check); ...@@ -1646,6 +1637,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check);
* drm_atomic_async_check() succeeds. Async commits are not supposed to swap * 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 * the states like normal sync commits, but just do in-place changes on the
* current state. * current state.
*
* TODO: Implement full swap instead of doing in-place changes.
*/ */
void drm_atomic_helper_async_commit(struct drm_device *dev, void drm_atomic_helper_async_commit(struct drm_device *dev,
struct drm_atomic_state *state) struct drm_atomic_state *state)
...@@ -1656,6 +1649,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev, ...@@ -1656,6 +1649,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
int i; int i;
for_each_new_plane_in_state(state, plane, plane_state, 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 = plane->helper_private;
funcs->atomic_async_update(plane, plane_state); funcs->atomic_async_update(plane, plane_state);
...@@ -1664,11 +1660,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev, ...@@ -1664,11 +1660,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
* plane->state in-place, make sure at least common * plane->state in-place, make sure at least common
* properties have been properly updated. * 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_x != plane_state->crtc_x);
WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y); 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_x != plane_state->src_x);
WARN_ON_ONCE(plane->state->src_y != plane_state->src_y); 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); EXPORT_SYMBOL(drm_atomic_helper_async_commit);
......
...@@ -502,6 +502,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane, ...@@ -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, static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
struct drm_plane_state *new_state) 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_x = new_state->src_x;
plane->state->src_y = new_state->src_y; plane->state->src_y = new_state->src_y;
plane->state->crtc_x = new_state->crtc_x; plane->state->crtc_x = new_state->crtc_x;
...@@ -524,6 +526,8 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane, ...@@ -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(plane->state) =
*to_mdp5_plane_state(new_state); *to_mdp5_plane_state(new_state);
new_state->fb = old_fb;
} }
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { 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, ...@@ -924,29 +924,17 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
struct drm_plane_state *new_state) struct drm_plane_state *new_state)
{ {
struct vop *vop = to_vop(plane->state->crtc); 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_x = new_state->crtc_x; plane->state->crtc_y = new_state->crtc_y;
plane_state->crtc_y = new_state->crtc_y; plane->state->crtc_h = new_state->crtc_h;
plane_state->crtc_h = new_state->crtc_h; plane->state->crtc_w = new_state->crtc_w;
plane_state->crtc_w = new_state->crtc_w; plane->state->src_x = new_state->src_x;
plane_state->src_x = new_state->src_x; plane->state->src_y = new_state->src_y;
plane_state->src_y = new_state->src_y; plane->state->src_h = new_state->src_h;
plane_state->src_h = new_state->src_h; plane->state->src_w = new_state->src_w;
plane_state->src_w = new_state->src_w; swap(plane->state->fb, new_state->fb);
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);
}
if (vop->is_enabled) { if (vop->is_enabled) {
rockchip_drm_psr_inhibit_get_state(new_state->state); rockchip_drm_psr_inhibit_get_state(new_state->state);
...@@ -955,9 +943,22 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane, ...@@ -955,9 +943,22 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
vop_cfg_done(vop); vop_cfg_done(vop);
spin_unlock(&vop->reg_lock); spin_unlock(&vop->reg_lock);
rockchip_drm_psr_inhibit_put_state(new_state->state); 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 = { 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, ...@@ -1025,7 +1025,7 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
{ {
struct vc4_plane_state *vc4_state, *new_vc4_state; 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_x = state->crtc_x;
plane->state->crtc_y = state->crtc_y; plane->state->crtc_y = state->crtc_y;
plane->state->crtc_w = state->crtc_w; plane->state->crtc_w = state->crtc_w;
......
...@@ -1185,6 +1185,14 @@ struct drm_plane_helper_funcs { ...@@ -1185,6 +1185,14 @@ struct drm_plane_helper_funcs {
* current one with the new plane configurations in the new * current one with the new plane configurations in the new
* plane_state. * 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: * FIXME:
* - It only works for single plane updates * - It only works for single plane updates
* - Async Pageflips are not supported yet * - Async Pageflips are not supported yet
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment