From patchwork Mon Mar 4 14:49:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helen Mae Koike Fornazier X-Patchwork-Id: 10837849 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E8A217E9 for ; Mon, 4 Mar 2019 14:49:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7C0BF2A00A for ; Mon, 4 Mar 2019 14:49:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6FD122A0F8; Mon, 4 Mar 2019 14:49:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F0D982A00A for ; Mon, 4 Mar 2019 14:49:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id AA5A989CE1; Mon, 4 Mar 2019 14:49:29 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by gabe.freedesktop.org (Postfix) with ESMTPS id 781EB89CE1 for ; Mon, 4 Mar 2019 14:49:28 +0000 (UTC) Received: from localhost.localdomain (unknown [IPv6:2804:431:9718:a1b1:9d17:4c45:79a4:9c61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: koike) by bhuna.collabora.co.uk (Postfix) with ESMTPSA id 58BB1261176; Mon, 4 Mar 2019 14:49:23 +0000 (GMT) From: Helen Koike To: dri-devel@lists.freedesktop.org, nicholas.kazlauskas@amd.com Subject: [PATCH 1/5] drm: don't block fb changes for async plane updates Date: Mon, 4 Mar 2019 11:49:05 -0300 Message-Id: <20190304144909.6267-2-helen.koike@collabora.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190304144909.6267-1-helen.koike@collabora.com> References: <20190304144909.6267-1-helen.koike@collabora.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?St=C3=A9phane_Marchesin?= , Sean Paul , David Airlie , daniel.vetter@ffwll.ch, linux-kernel@vger.kernel.org, Tomasz Figa , boris.brezillon@collabora.com, kernel@collabora.com Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 ballanced. Cc: # v4.14+: 25dc194b34dd: drm: Block fb changes for async plane updates Fixes: 25dc194b34dd ("drm: Block fb changes for async plane updates") Suggested-by: Boris Brezillon Signed-off-by: Helen Koike --- Hello, As mentioned in the cover letter, I tested on the rockchip and on i915 (with a patch I am still working on for replacing cursors by async update), with igt plane_cursor_legacy and kms_cursor_legacy and I didn't see any regressions. I couldn't test on MSM and AMD because I don't have the hardware (and I am having some issues testing on vc4) and I would appreciate if anyone could help me testing those. I also think it would be a better solution if, instead of having async to do in-place updates in the current state, the async path should be equivalent to a syncronous update, i.e., modifying new_state and performing a flip IMHO, the only difference between sync and async should be that async update doesn't wait for vblank and applies the changes immeditally to the hw, but the code path could be almost the same. But for now I think this solution is ok (swaping new_fb/old_fb), and then we can adjust things little by little, what do you think? Thanks! Helen drivers/gpu/drm/drm_atomic_helper.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 540a77a2ade9..e7eb96f1efc2 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1608,15 +1608,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; @@ -1657,6 +1648,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); @@ -1665,11 +1659,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);