All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
To: dri-devel@lists.freedesktop.org
Cc: Gustavo Padovan <gustavo.padovan@collabora.com>,
	intel-gfx@lists.freedesktop.org
Subject: [PATCH v2 6/6] drm/atomic: Make async plane update checks work as intended, v2.
Date: Mon,  4 Sep 2017 12:48:38 +0200	[thread overview]
Message-ID: <20170904104838.23822-7-maarten.lankhorst@linux.intel.com> (raw)
In-Reply-To: <20170904104838.23822-1-maarten.lankhorst@linux.intel.com>

By always keeping track of the last commit in plane_state, we know
whether there is an active update on the plane or not. With that
information we can reject the fast update, and force the slowpath
to be used as was originally intended.

We cannot use plane_state->crtc->state here, because this only mentions
the most recent commit for the crtc, but not the planes that were part
of it. We specifically care about what the last commit involving this
plane is, which can only be tracked with a pointer in the plane state.

Changes since v1:
- Clean up the whole function here, instead of partially earlier.
- Add mention in the commit message why we need commit in plane_state.
- Swap plane->state in intel_legacy_cursor_update, instead of
  reassigning all variables. With this commit We know that the cursor
  is not part of any active commits so this hack can be removed.

Cc: Gustavo Padovan <gustavo.padovan@collabora.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> #v1
---
 drivers/gpu/drm/drm_atomic_helper.c  | 53 ++++++++++--------------------------
 drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++-------
 include/drm/drm_plane.h              |  5 ++--
 3 files changed, 35 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index c81d46927a74..a2cd432d8b2d 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1388,35 +1388,31 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
-	struct drm_crtc_commit *commit;
-	struct drm_plane *__plane, *plane = NULL;
-	struct drm_plane_state *__plane_state, *plane_state = NULL;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state, *new_plane_state;
 	const struct drm_plane_helper_funcs *funcs;
-	int i, j, n_planes = 0;
+	int i, n_planes = 0;
 
 	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 		if (drm_atomic_crtc_needs_modeset(crtc_state))
 			return -EINVAL;
 	}
 
-	for_each_new_plane_in_state(state, __plane, __plane_state, i) {
+	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i)
 		n_planes++;
-		plane = __plane;
-		plane_state = __plane_state;
-	}
 
 	/* FIXME: we support only single plane updates for now */
-	if (!plane || n_planes != 1)
+	if (n_planes != 1)
 		return -EINVAL;
 
-	if (!plane_state->crtc)
+	if (!new_plane_state->crtc)
 		return -EINVAL;
 
 	funcs = plane->helper_private;
 	if (!funcs->atomic_async_update)
 		return -EINVAL;
 
-	if (plane_state->fence)
+	if (new_plane_state->fence)
 		return -EINVAL;
 
 	/*
@@ -1424,31 +1420,11 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
 	 * the plane.  This prevents our async update's changes from getting
 	 * overridden by a previous synchronous update's state.
 	 */
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
-		if (plane->crtc != crtc)
-			continue;
-
-		spin_lock(&crtc->commit_lock);
-		commit = list_first_entry_or_null(&crtc->commit_list,
-						  struct drm_crtc_commit,
-						  commit_entry);
-		if (!commit) {
-			spin_unlock(&crtc->commit_lock);
-			continue;
-		}
-		spin_unlock(&crtc->commit_lock);
-
-		if (!crtc->state->state)
-			continue;
+	if (old_plane_state->commit &&
+	    !try_wait_for_completion(&old_plane_state->commit->hw_done))
+		return -EBUSY;
 
-		for_each_plane_in_state(crtc->state->state, __plane,
-					__plane_state, j) {
-			if (__plane == plane)
-				return -EINVAL;
-		}
-	}
-
-	return funcs->atomic_async_check(plane, plane_state);
+	return funcs->atomic_async_check(plane, new_plane_state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_async_check);
 
@@ -1814,9 +1790,10 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
 	}
 
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
-		/* commit tracked through new_crtc_state->commit, no need to do it explicitly */
-		if (new_plane_state->crtc)
-			continue;
+		/*
+		 * Unlike connectors, always track planes explicitly for
+		 * async pageflip support.
+		 */
 
 		/* Userspace is not allowed to get ahead of the previous
 		 * commit with nonblocking ones. */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7abbc761a635..0add029d95f6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13064,6 +13064,14 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 		goto slow;
 
 	old_plane_state = plane->state;
+	/*
+	 * Don't do an async update if there is an outstanding commit modifying
+	 * the plane.  This prevents our async update's changes from getting
+	 * overridden by a previous synchronous update's state.
+	 */
+	if (old_plane_state->commit &&
+	    !try_wait_for_completion(&old_plane_state->commit->hw_done))
+		goto slow;
 
 	/*
 	 * If any parameters change that may affect watermarks,
@@ -13125,19 +13133,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 	}
 
 	old_fb = old_plane_state->fb;
-	old_vma = to_intel_plane_state(old_plane_state)->vma;
 
 	i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb),
 			  intel_plane->frontbuffer_bit);
 
 	/* Swap plane state */
-	new_plane_state->fence = old_plane_state->fence;
-	new_plane_state->commit = old_plane_state->commit;
-	*to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state);
-	new_plane_state->fence = NULL;
-	new_plane_state->commit = NULL;
-	new_plane_state->fb = old_fb;
-	to_intel_plane_state(new_plane_state)->vma = NULL;
+	plane->state = new_plane_state;
 
 	if (plane->state->visible) {
 		trace_intel_update_plane(plane, to_intel_crtc(crtc));
@@ -13149,13 +13150,19 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 		intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
 	}
 
-	if (old_vma)
+	old_vma = to_intel_plane_state(old_plane_state)->vma;
+	if (old_vma) {
+		to_intel_plane_state(old_plane_state)->vma = NULL;
 		intel_unpin_fb_vma(old_vma);
+	}
 
 out_unlock:
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 out_free:
-	intel_plane_destroy_state(plane, new_plane_state);
+	if (ret)
+		intel_plane_destroy_state(plane, new_plane_state);
+	else
+		intel_plane_destroy_state(plane, old_plane_state);
 	return ret;
 
 slow:
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 7d96116fd4c4..feb9941d0cdb 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -124,9 +124,10 @@ struct drm_plane_state {
 	bool visible;
 
 	/**
-	 * @commit: Tracks the pending commit to prevent use-after-free conditions.
+	 * @commit: Tracks the pending commit to prevent use-after-free conditions,
+	 * and for async plane updates.
 	 *
-	 * Is only set when @crtc is NULL.
+	 * May be NULL.
 	 */
 	struct drm_crtc_commit *commit;
 
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2017-09-04 10:48 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-04 10:48 [PATCH v2 0/6] drm/atomic: Fix use-after-free with unbound connectors/planes Maarten Lankhorst
2017-09-04 10:48 ` [PATCH v2 1/6] drm/i915: Always wait for flip_done, v2 Maarten Lankhorst
2017-09-07  9:49   ` Daniel Vetter
2017-09-08  9:08     ` Maarten Lankhorst
2017-09-04 10:48 ` [PATCH v2 2/6] drm/atomic: Move drm_crtc_commit to drm_crtc_state, v3 Maarten Lankhorst
2017-09-04 15:04   ` [PATCH] drm/atomic: Move drm_crtc_commit to drm_crtc_state, v4 Maarten Lankhorst
2017-09-04 18:01     ` kbuild test robot
2017-09-05  6:25     ` Daniel Vetter
2017-09-04 10:48 ` [PATCH v2 3/6] drm/atomic: Remove waits in drm_atomic_helper_commit_cleanup_done, v2 Maarten Lankhorst
2017-09-04 10:48 ` [PATCH v2 4/6] drm/atomic: Return commit in drm_crtc_commit_get for better annotation Maarten Lankhorst
2017-09-07  9:59   ` Daniel Vetter
2017-09-04 10:48 ` [PATCH v2 5/6] drm/atomic: Fix freeing connector/plane state too early by tracking commits, v3 Maarten Lankhorst
2017-09-07 10:05   ` Daniel Vetter
2017-09-07 11:08     ` Maarten Lankhorst
2017-09-04 10:48 ` Maarten Lankhorst [this message]
     [not found]   ` <20170904104838.23822-7-maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2017-09-24 14:33     ` [PATCH v2 6/6] drm/atomic: Make async plane update checks work as intended, v2 Dmitry Osipenko
     [not found]       ` <54467116-df02-e6ad-ac14-90aa79e164e4-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-09-25  6:43         ` [PATCH] drm/atomic: Make async plane update checks actually work as intended Maarten Lankhorst
     [not found]           ` <a7d5fb04-c2f5-b743-5940-a1bd181d780d-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2017-09-25 14:08             ` Dmitry Osipenko
2017-09-26  4:59             ` Daniel Vetter
2017-09-04 11:11 ` ✓ Fi.CI.BAT: success for drm/atomic: Fix use-after-free with unbound connectors/planes. (rev2) Patchwork
2017-09-04 12:45 ` ✗ Fi.CI.IGT: failure " Patchwork
2017-09-04 15:23 ` ✓ Fi.CI.BAT: success for drm/atomic: Fix use-after-free with unbound connectors/planes. (rev3) Patchwork
2017-09-04 16:21 ` ✗ Fi.CI.IGT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170904104838.23822-7-maarten.lankhorst@linux.intel.com \
    --to=maarten.lankhorst@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gustavo.padovan@collabora.com \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.