From: Greg Kroah-Hartman Date: Thu, 13 Jun 2019 07:54:17 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v5.1.10~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=19477147cb096efaf8108e015bca1da8f87b974a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: drm-don-t-block-fb-changes-for-async-plane-updates.patch --- diff --git a/queue-4.14/drm-don-t-block-fb-changes-for-async-plane-updates.patch b/queue-4.14/drm-don-t-block-fb-changes-for-async-plane-updates.patch new file mode 100644 index 00000000000..25ab0582e2f --- /dev/null +++ b/queue-4.14/drm-don-t-block-fb-changes-for-async-plane-updates.patch @@ -0,0 +1,104 @@ +From 89a4aac0ab0e6f5eea10d7bf4869dd15c3de2cd4 Mon Sep 17 00:00:00 2001 +From: Helen Koike +Date: Mon, 3 Jun 2019 13:56:10 -0300 +Subject: drm: don't block fb changes for async plane updates + +From: Helen Koike + +commit 89a4aac0ab0e6f5eea10d7bf4869dd15c3de2cd4 upstream. + +In the case of a normal sync update, the preparation of framebuffers (be +it calling drm_atomic_helper_prepare_planes() or doing setups with +drm_framebuffer_get()) are performed in the new_state and the respective +cleanups are performed in the old_state. + +In the case of async updates, the preparation is also done in the +new_state but the cleanups are done in the new_state (because updates +are performed in place, i.e. in the current state). + +The current code blocks async udpates when the fb is changed, turning +async updates into sync updates, slowing down cursor updates and +introducing regressions in igt tests with errors of type: + +"CRITICAL: completed 97 cursor updated in a period of 30 flips, we +expect to complete approximately 15360 updates, with the threshold set +at 7680" + +Fb changes in async updates were prevented to avoid the following scenario: + +- Async update, oldfb = NULL, newfb = fb1, prepare fb1, cleanup fb1 +- Async update, oldfb = fb1, newfb = fb2, prepare fb2, cleanup fb2 +- Non-async commit, oldfb = fb2, newfb = fb1, prepare fb1, cleanup fb2 (wrong) +Where we have a single call to prepare fb2 but double cleanup call to fb2. + +To solve the above problems, instead of blocking async fb changes, we +place the old framebuffer in the new_state object, so when the code +performs cleanups in the new_state it will cleanup the old_fb and we +will have the following scenario instead: + +- Async update, oldfb = NULL, newfb = fb1, prepare fb1, no cleanup +- Async update, oldfb = fb1, newfb = fb2, prepare fb2, cleanup fb1 +- Non-async commit, oldfb = fb2, newfb = fb1, prepare fb1, cleanup fb2 + +Where calls to prepare/cleanup are balanced. + +Cc: # v4.14+ +Fixes: 25dc194b34dd ("drm: Block fb changes for async plane updates") +Suggested-by: Boris Brezillon +Signed-off-by: Helen Koike +Reviewed-by: Boris Brezillon +Reviewed-by: Nicholas Kazlauskas +Signed-off-by: Boris Brezillon +Link: https://patchwork.freedesktop.org/patch/msgid/20190603165610.24614-6-helen.koike@collabora.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_atomic_helper.c | 10 ++++++++++ + include/drm/drm_modeset_helper_vtables.h | 8 ++++++++ + 2 files changed, 18 insertions(+) + +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -1462,6 +1462,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_ch + * 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) +@@ -1472,8 +1474,16 @@ void drm_atomic_helper_async_commit(stru + int i; + + for_each_new_plane_in_state(state, plane, plane_state, i) { ++ struct drm_framebuffer *old_fb = plane->state->fb; ++ + funcs = plane->helper_private; + funcs->atomic_async_update(plane, plane_state); ++ ++ /* ++ * 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); +--- a/include/drm/drm_modeset_helper_vtables.h ++++ b/include/drm/drm_modeset_helper_vtables.h +@@ -1159,6 +1159,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 diff --git a/queue-4.14/series b/queue-4.14/series index 6b62443821c..5624d8a0e40 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -78,3 +78,4 @@ gpio-vf610-do-not-share-irq_chip.patch percpu-do-not-search-past-bitmap-when-allocating-an-.patch revert-bluetooth-align-minimum-encryption-key-size-for-le-and-br-edr-connections.patch revert-drm-nouveau-add-kconfig-option-to-turn-off-nouveau-legacy-contexts.-v3.patch +drm-don-t-block-fb-changes-for-async-plane-updates.patch