diff options
author | Dave Airlie <airlied@redhat.com> | 2019-06-05 21:56:00 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-06-05 21:57:13 -0400 |
commit | dbd9f78ed23746e9708f773224eec2c8b33206e7 (patch) | |
tree | c3402e3caf21d9636f3d241d819b536adb0fd735 | |
parent | 75cb3776fdffa94b424406aeb0efb76b122990f5 (diff) | |
parent | 283f1e383e91d96fe652fad549537ae15cf31d60 (diff) |
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
-rw-r--r-- | drivers/dma-buf/udmabuf.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_plane.c | 2 | ||||
-rw-r--r-- | include/drm/drm_modeset_helper_vtables.h | 8 |
7 files changed, 53 insertions, 38 deletions
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index cd57747286f2..9635897458a0 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c | |||
@@ -77,6 +77,7 @@ static void unmap_udmabuf(struct dma_buf_attachment *at, | |||
77 | struct sg_table *sg, | 77 | struct sg_table *sg, |
78 | enum dma_data_direction direction) | 78 | enum dma_data_direction direction) |
79 | { | 79 | { |
80 | dma_unmap_sg(at->dev, sg->sgl, sg->nents, direction); | ||
80 | sg_free_table(sg); | 81 | sg_free_table(sg); |
81 | kfree(sg); | 82 | kfree(sg); |
82 | } | 83 | } |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index bcb1a93c0b4c..ab7c5c3004ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -4232,8 +4232,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane, | |||
4232 | struct drm_plane_state *old_state = | 4232 | struct drm_plane_state *old_state = |
4233 | drm_atomic_get_old_plane_state(new_state->state, plane); | 4233 | drm_atomic_get_old_plane_state(new_state->state, plane); |
4234 | 4234 | ||
4235 | if (plane->state->fb != new_state->fb) | 4235 | swap(plane->state->fb, new_state->fb); |
4236 | drm_atomic_set_fb_for_plane(plane->state, new_state->fb); | ||
4237 | 4236 | ||
4238 | plane->state->src_x = new_state->src_x; | 4237 | plane->state->src_x = new_state->src_x; |
4239 | plane->state->src_y = new_state->src_y; | 4238 | plane->state->src_y = new_state->src_y; |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2e0cb4246cbd..22a5c617f670 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
@@ -1607,15 +1607,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev, | |||
1607 | old_plane_state->crtc != new_plane_state->crtc) | 1607 | old_plane_state->crtc != new_plane_state->crtc) |
1608 | return -EINVAL; | 1608 | return -EINVAL; |
1609 | 1609 | ||
1610 | /* | ||
1611 | * FIXME: Since prepare_fb and cleanup_fb are always called on | ||
1612 | * the new_plane_state for async updates we need to block framebuffer | ||
1613 | * changes. This prevents use of a fb that's been cleaned up and | ||
1614 | * double cleanups from occuring. | ||
1615 | */ | ||
1616 | if (old_plane_state->fb != new_plane_state->fb) | ||
1617 | return -EINVAL; | ||
1618 | |||
1619 | funcs = plane->helper_private; | 1610 | funcs = plane->helper_private; |
1620 | if (!funcs->atomic_async_update) | 1611 | if (!funcs->atomic_async_update) |
1621 | return -EINVAL; | 1612 | return -EINVAL; |
@@ -1646,6 +1637,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check); | |||
1646 | * drm_atomic_async_check() succeeds. Async commits are not supposed to swap | 1637 | * drm_atomic_async_check() succeeds. Async commits are not supposed to swap |
1647 | * the states like normal sync commits, but just do in-place changes on the | 1638 | * the states like normal sync commits, but just do in-place changes on the |
1648 | * current state. | 1639 | * current state. |
1640 | * | ||
1641 | * TODO: Implement full swap instead of doing in-place changes. | ||
1649 | */ | 1642 | */ |
1650 | void drm_atomic_helper_async_commit(struct drm_device *dev, | 1643 | void drm_atomic_helper_async_commit(struct drm_device *dev, |
1651 | struct drm_atomic_state *state) | 1644 | struct drm_atomic_state *state) |
@@ -1656,6 +1649,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev, | |||
1656 | int i; | 1649 | int i; |
1657 | 1650 | ||
1658 | for_each_new_plane_in_state(state, plane, plane_state, i) { | 1651 | for_each_new_plane_in_state(state, plane, plane_state, i) { |
1652 | struct drm_framebuffer *new_fb = plane_state->fb; | ||
1653 | struct drm_framebuffer *old_fb = plane->state->fb; | ||
1654 | |||
1659 | funcs = plane->helper_private; | 1655 | funcs = plane->helper_private; |
1660 | funcs->atomic_async_update(plane, plane_state); | 1656 | funcs->atomic_async_update(plane, plane_state); |
1661 | 1657 | ||
@@ -1664,11 +1660,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev, | |||
1664 | * plane->state in-place, make sure at least common | 1660 | * plane->state in-place, make sure at least common |
1665 | * properties have been properly updated. | 1661 | * properties have been properly updated. |
1666 | */ | 1662 | */ |
1667 | WARN_ON_ONCE(plane->state->fb != plane_state->fb); | 1663 | WARN_ON_ONCE(plane->state->fb != new_fb); |
1668 | WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x); | 1664 | WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x); |
1669 | WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y); | 1665 | WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y); |
1670 | WARN_ON_ONCE(plane->state->src_x != plane_state->src_x); | 1666 | WARN_ON_ONCE(plane->state->src_x != plane_state->src_x); |
1671 | WARN_ON_ONCE(plane->state->src_y != plane_state->src_y); | 1667 | WARN_ON_ONCE(plane->state->src_y != plane_state->src_y); |
1668 | |||
1669 | /* | ||
1670 | * Make sure the FBs have been swapped so that cleanups in the | ||
1671 | * new_state performs a cleanup in the old FB. | ||
1672 | */ | ||
1673 | WARN_ON_ONCE(plane_state->fb != old_fb); | ||
1672 | } | 1674 | } |
1673 | } | 1675 | } |
1674 | EXPORT_SYMBOL(drm_atomic_helper_async_commit); | 1676 | EXPORT_SYMBOL(drm_atomic_helper_async_commit); |
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c index be13140967b4..b854f471e9e5 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | |||
@@ -502,6 +502,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane, | |||
502 | static void mdp5_plane_atomic_async_update(struct drm_plane *plane, | 502 | static void mdp5_plane_atomic_async_update(struct drm_plane *plane, |
503 | struct drm_plane_state *new_state) | 503 | struct drm_plane_state *new_state) |
504 | { | 504 | { |
505 | struct drm_framebuffer *old_fb = plane->state->fb; | ||
506 | |||
505 | plane->state->src_x = new_state->src_x; | 507 | plane->state->src_x = new_state->src_x; |
506 | plane->state->src_y = new_state->src_y; | 508 | plane->state->src_y = new_state->src_y; |
507 | plane->state->crtc_x = new_state->crtc_x; | 509 | plane->state->crtc_x = new_state->crtc_x; |
@@ -524,6 +526,8 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane, | |||
524 | 526 | ||
525 | *to_mdp5_plane_state(plane->state) = | 527 | *to_mdp5_plane_state(plane->state) = |
526 | *to_mdp5_plane_state(new_state); | 528 | *to_mdp5_plane_state(new_state); |
529 | |||
530 | new_state->fb = old_fb; | ||
527 | } | 531 | } |
528 | 532 | ||
529 | static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { | 533 | static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { |
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 20a9c296d027..3bb242f7d32f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c | |||
@@ -924,29 +924,17 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane, | |||
924 | struct drm_plane_state *new_state) | 924 | struct drm_plane_state *new_state) |
925 | { | 925 | { |
926 | struct vop *vop = to_vop(plane->state->crtc); | 926 | struct vop *vop = to_vop(plane->state->crtc); |
927 | struct drm_plane_state *plane_state; | 927 | struct drm_framebuffer *old_fb = plane->state->fb; |
928 | 928 | ||
929 | plane_state = plane->funcs->atomic_duplicate_state(plane); | 929 | plane->state->crtc_x = new_state->crtc_x; |
930 | plane_state->crtc_x = new_state->crtc_x; | 930 | plane->state->crtc_y = new_state->crtc_y; |
931 | plane_state->crtc_y = new_state->crtc_y; | 931 | plane->state->crtc_h = new_state->crtc_h; |
932 | plane_state->crtc_h = new_state->crtc_h; | 932 | plane->state->crtc_w = new_state->crtc_w; |
933 | plane_state->crtc_w = new_state->crtc_w; | 933 | plane->state->src_x = new_state->src_x; |
934 | plane_state->src_x = new_state->src_x; | 934 | plane->state->src_y = new_state->src_y; |
935 | plane_state->src_y = new_state->src_y; | 935 | plane->state->src_h = new_state->src_h; |
936 | plane_state->src_h = new_state->src_h; | 936 | plane->state->src_w = new_state->src_w; |
937 | plane_state->src_w = new_state->src_w; | 937 | swap(plane->state->fb, new_state->fb); |
938 | |||
939 | if (plane_state->fb != new_state->fb) | ||
940 | drm_atomic_set_fb_for_plane(plane_state, new_state->fb); | ||
941 | |||
942 | swap(plane_state, plane->state); | ||
943 | |||
944 | if (plane->state->fb && plane->state->fb != new_state->fb) { | ||
945 | drm_framebuffer_get(plane->state->fb); | ||
946 | WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0); | ||
947 | drm_flip_work_queue(&vop->fb_unref_work, plane->state->fb); | ||
948 | set_bit(VOP_PENDING_FB_UNREF, &vop->pending); | ||
949 | } | ||
950 | 938 | ||
951 | if (vop->is_enabled) { | 939 | if (vop->is_enabled) { |
952 | rockchip_drm_psr_inhibit_get_state(new_state->state); | 940 | 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 | vop_cfg_done(vop); | 943 | vop_cfg_done(vop); |
956 | spin_unlock(&vop->reg_lock); | 944 | spin_unlock(&vop->reg_lock); |
957 | rockchip_drm_psr_inhibit_put_state(new_state->state); | 945 | rockchip_drm_psr_inhibit_put_state(new_state->state); |
958 | } | ||
959 | 946 | ||
960 | plane->funcs->atomic_destroy_state(plane, plane_state); | 947 | /* |
948 | * A scanout can still be occurring, so we can't drop the | ||
949 | * reference to the old framebuffer. To solve this we get a | ||
950 | * reference to old_fb and set a worker to release it later. | ||
951 | * FIXME: if we perform 500 async_update calls before the | ||
952 | * vblank, then we can have 500 different framebuffers waiting | ||
953 | * to be released. | ||
954 | */ | ||
955 | if (old_fb && plane->state->fb != old_fb) { | ||
956 | drm_framebuffer_get(old_fb); | ||
957 | WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0); | ||
958 | drm_flip_work_queue(&vop->fb_unref_work, old_fb); | ||
959 | set_bit(VOP_PENDING_FB_UNREF, &vop->pending); | ||
960 | } | ||
961 | } | ||
961 | } | 962 | } |
962 | 963 | ||
963 | static const struct drm_plane_helper_funcs plane_helper_funcs = { | 964 | static const struct drm_plane_helper_funcs plane_helper_funcs = { |
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 4d918d3e4858..afc80b245ea3 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c | |||
@@ -1025,7 +1025,7 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, | |||
1025 | { | 1025 | { |
1026 | struct vc4_plane_state *vc4_state, *new_vc4_state; | 1026 | struct vc4_plane_state *vc4_state, *new_vc4_state; |
1027 | 1027 | ||
1028 | drm_atomic_set_fb_for_plane(plane->state, state->fb); | 1028 | swap(plane->state->fb, state->fb); |
1029 | plane->state->crtc_x = state->crtc_x; | 1029 | plane->state->crtc_x = state->crtc_x; |
1030 | plane->state->crtc_y = state->crtc_y; | 1030 | plane->state->crtc_y = state->crtc_y; |
1031 | plane->state->crtc_w = state->crtc_w; | 1031 | plane->state->crtc_w = state->crtc_w; |
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index f9c94c2a1364..f7bbd0b0ecd1 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h | |||
@@ -1185,6 +1185,14 @@ struct drm_plane_helper_funcs { | |||
1185 | * current one with the new plane configurations in the new | 1185 | * current one with the new plane configurations in the new |
1186 | * plane_state. | 1186 | * plane_state. |
1187 | * | 1187 | * |
1188 | * Drivers should also swap the framebuffers between current plane | ||
1189 | * state (&drm_plane.state) and new_state. | ||
1190 | * This is required since cleanup for async commits is performed on | ||
1191 | * the new state, rather than old state like for traditional commits. | ||
1192 | * Since we want to give up the reference on the current (old) fb | ||
1193 | * instead of our brand new one, swap them in the driver during the | ||
1194 | * async commit. | ||
1195 | * | ||
1188 | * FIXME: | 1196 | * FIXME: |
1189 | * - It only works for single plane updates | 1197 | * - It only works for single plane updates |
1190 | * - Async Pageflips are not supported yet | 1198 | * - Async Pageflips are not supported yet |