All of lore.kernel.org
 help / color / mirror / Atom feed
From: ville.syrjala@linux.intel.com
To: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org
Subject: [PATCH 10/13] HACK: drm/i915: Make non-blocking GPU synchronization optional
Date: Fri, 16 Nov 2012 16:22:22 +0200	[thread overview]
Message-ID: <1353075745-30115-11-git-send-email-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <1353075745-30115-1-git-send-email-ville.syrjala@linux.intel.com>

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a module parameter that allows one to easily change between blocking
and non-blocking GPU synchronization with atomic page flips.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_stub.c          |    5 ++
 drivers/gpu/drm/i915/i915_trace.h   |   49 ++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |  119 ++++++++++++++++++++++++++++++++++-
 3 files changed, 172 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index c236fd2..a6149f4 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -46,16 +46,21 @@ EXPORT_SYMBOL(drm_vblank_offdelay);
 unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
 EXPORT_SYMBOL(drm_timestamp_precision);
 
+unsigned int drm_async_gpu = 1;	/* 1 to enable async gpu wait */
+EXPORT_SYMBOL(drm_async_gpu);
+
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output");
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(async_gpu, "Async GPU wait");
 
 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(async_gpu, drm_async_gpu, int, 0600);
 
 struct idr drm_minors_idr;
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index f71e1b3..754a204 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,55 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_flip,
+	    TP_PROTO(bool sprite, int pipe, int action, u32 commit_surf, u32 commit_surflive, u32 surf, u32 surflive, u32 iir, u32 commit_dsl, u32 dsl, u32 flip_vbl_count, u32 vbl_count),
+	    TP_ARGS(sprite, pipe, action, commit_surf, commit_surflive, surf, surflive, iir, commit_dsl, dsl, flip_vbl_count, vbl_count),
+
+	    TP_STRUCT__entry(
+			     __field(bool, sprite)
+			     __field(int, pipe)
+			     __field(int, action)
+			     __field(u32, commit_surf)
+			     __field(u32, commit_surflive)
+			     __field(u32, surf)
+			     __field(u32, surflive)
+			     __field(u32, iir)
+			     __field(u32, commit_dsl)
+			     __field(u32, dsl)
+			     __field(u32, flip_vbl_count)
+			     __field(u32, vbl_count)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->sprite = sprite;
+			   __entry->pipe = pipe;
+			   __entry->action = action;
+			   __entry->commit_surf = commit_surf;
+			   __entry->commit_surflive = commit_surflive;
+			   __entry->surf = surf;
+			   __entry->surflive = surflive;
+			   __entry->iir = iir;
+			   __entry->commit_dsl = commit_dsl;
+			   __entry->dsl = dsl;
+			   __entry->flip_vbl_count = flip_vbl_count;
+			   __entry->vbl_count = vbl_count;
+			   ),
+
+	    TP_printk(
+		      "%s/%d %s commit_surf=%x commit_surflive=%x surf=%x surflive=%x iir=%x commit_dsl=%u dsl=%u flip_vbl_count=%u vbl_count=%u",
+		      __entry->sprite ? "SPR" : "DSP", __entry->pipe,
+		      __entry->action == 0 ? "new" :
+		      __entry->action == 1 ? "flipped" :
+		      __entry->action == 2 ? "not flipped" :
+		      __entry->action == 3 ? "missed flipped" : "?",
+		      __entry->commit_surf, __entry->commit_surflive,
+		      __entry->surf, __entry->surflive,
+		      __entry->iir,
+		      __entry->commit_dsl, __entry->dsl,
+		      __entry->flip_vbl_count, __entry->vbl_count
+		      )
+);
+
 TRACE_EVENT(i915_flip_queue_len,
 	    TP_PROTO(unsigned int queue_len),
 	    TP_ARGS(queue_len),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index f2e6d88..170ac6f 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -34,6 +34,8 @@
 #define USE_OLR
 //#define FORCE_CACHE_FLUSH
 
+//#define SURFLIVE_DEBUG
+
 struct intel_flip {
 	struct drm_flip base;
 	u32 vbl_count;
@@ -51,6 +53,11 @@ struct intel_flip {
 	unsigned int flip_seq;
 	/* FIXME need cursor regs too */
 	struct intel_plane_regs regs;
+#ifdef SURFLIVE_DEBUG
+	u32 commit_dsl;
+	u32 commit_surf;
+	u32 commit_surflive;
+#endif
 };
 
 struct intel_plane_state {
@@ -806,11 +813,13 @@ static void unpin_fbs(struct drm_device *dev,
 	}
 }
 
+extern unsigned int drm_async_gpu;
+
 static int pin_fbs(struct drm_device *dev,
 		   struct intel_atomic_state *s)
 {
 	int i, ret;
-	bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK;
+	bool nonblock = drm_async_gpu && (s->flags & DRM_MODE_ATOMIC_NONBLOCK);
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
@@ -1971,6 +1980,48 @@ static void intel_flip_prepare(struct drm_flip *flip)
 	}
 }
 
+#ifdef SURFLIVE_DEBUG
+enum flip_action {
+	_NEW,
+	_FLIPPED,
+	_NOT_FLIPPED,
+	_MISSED_FLIPPED,
+};
+
+static void trace_flip(struct intel_flip *intel_flip, enum flip_action action)
+{
+	struct drm_crtc *crtc = intel_flip->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = to_intel_crtc(crtc)->pipe;
+	u32 surf;
+	u32 surflive;
+	u32 dsl;
+	u32 iir;
+	u32 vbl_count;
+
+	if (intel_flip->plane) {
+		surf = I915_READ(SPRSURF(pipe));
+		surflive = I915_READ(SPRSURFLIVE(pipe));
+	} else {
+		surf = I915_READ(DSPSURF(pipe));
+		surflive = I915_READ(DSPSURFLIVE(pipe));
+	}
+	dsl = I915_READ(PIPEDSL(pipe));
+	iir = I915_READ(DEIIR);
+	vbl_count = get_vbl_count(crtc);
+
+	trace_i915_atomic_flip(intel_flip->plane != NULL, pipe, action,
+			       intel_flip->commit_surf, intel_flip->commit_surflive,
+			       surf, surflive, iir, intel_flip->commit_dsl, dsl,
+			       intel_flip->vbl_count, vbl_count);
+}
+#endif
+
+#ifdef SURFLIVE_DEBUG
+static unsigned int missed_flips;
+#endif
+
 static bool intel_flip_flip(struct drm_flip *flip,
 			    struct drm_flip *pending_flip)
 {
@@ -1980,6 +2031,9 @@ static bool intel_flip_flip(struct drm_flip *flip,
 	struct drm_device *dev = crtc->dev;
 	int pipe = intel_crtc->pipe;
 	u32 vbl_count;
+#ifdef SURFLIVE_DEBUG
+	struct drm_i915_private *dev_priv = dev->dev_private;
+#endif
 
 	intel_flip->vblank_ref = drm_vblank_get(dev, pipe) == 0;
 
@@ -1991,10 +2045,26 @@ static bool intel_flip_flip(struct drm_flip *flip,
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
 		intel_plane->commit(plane, &intel_flip->regs);
+
+#ifdef SURFLIVE_DEBUG
+		intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe));
+		intel_flip->commit_surf = I915_READ(SPRSURF(pipe));
+		intel_flip->commit_surflive = I915_READ(SPRSURFLIVE(pipe));
+		if (intel_flip->commit_surf != intel_flip->regs.surf)
+			pr_err("SPRITE SURF MISMATCH\n");
+#endif
 	} else {
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
 		dev_priv->display.commit_plane(crtc, &intel_flip->regs);
+
+#ifdef SURFLIVE_DEBUG
+		intel_flip->commit_dsl = I915_READ(PIPEDSL(pipe));
+		intel_flip->commit_surf = I915_READ(DSPSURF(pipe));
+		intel_flip->commit_surflive = I915_READ(DSPSURFLIVE(pipe));
+		if (intel_flip->commit_surf != intel_flip->regs.surf)
+			pr_err("PRIMARY PLANE SURF MISMATCH\n");
+#endif
 	}
 
 	if (intel_flip->has_cursor)
@@ -2011,16 +2081,38 @@ static bool intel_flip_flip(struct drm_flip *flip,
 	else
 		intel_flip->vbl_count = (vbl_count + 1) & 0xffffff;
 
+#ifdef SURFLIVE_DEBUG
+	trace_flip(intel_flip, _NEW);
+#endif
+
 	if (pending_flip) {
 		struct intel_flip *old_intel_flip =
 			container_of(pending_flip, struct intel_flip, base);
 		bool flipped = intel_vbl_check(pending_flip, vbl_count);
 
 		if (!flipped) {
+#ifdef SURFLIVE_DEBUG
+			u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+			if (old_intel_flip->commit_surflive != surflive)
+				trace_flip(old_intel_flip, _NOT_FLIPPED);
+#endif
 			swap(intel_flip->old_fb_id, old_intel_flip->old_fb_id);
 			swap(intel_flip->old_bo, old_intel_flip->old_bo);
 			swap(intel_flip->old_cursor_bo, old_intel_flip->old_cursor_bo);
 		}
+#ifdef SURFLIVE_DEBUG
+		else {
+			u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+			if (old_intel_flip->commit_surf != surflive) {
+				trace_flip(old_intel_flip, _FLIPPED);
+				missed_flips++;
+				return false;
+			}
+			if (missed_flips)
+				trace_flip(old_intel_flip, _MISSED_FLIPPED);
+			missed_flips = 0;
+		}
+#endif
 
 		return flipped;
 	}
@@ -2034,7 +2126,26 @@ static bool intel_flip_vblank(struct drm_flip *pending_flip)
 		container_of(pending_flip, struct intel_flip, base);
 	u32 vbl_count = get_vbl_count(old_intel_flip->crtc);
 
+#ifdef SURFLIVE_DEBUG
+	struct drm_i915_private *dev_priv = old_intel_flip->crtc->dev->dev_private;
+	int pipe = to_intel_crtc(old_intel_flip->crtc)->pipe;
+	bool flipped;
+	flipped = intel_vbl_check(pending_flip, vbl_count);
+	if (flipped) {
+		u32 surflive = I915_READ(old_intel_flip->plane ? SPRSURFLIVE(pipe) : DSPSURFLIVE(pipe));
+		if (old_intel_flip->commit_surf != surflive) {
+			trace_flip(old_intel_flip, _FLIPPED);
+			missed_flips++;
+			return false;
+		}
+		if (missed_flips)
+			trace_flip(old_intel_flip, _MISSED_FLIPPED);
+		missed_flips = 0;
+	}
+	return flipped;
+#else
 	return intel_vbl_check(pending_flip, vbl_count);
+#endif
 }
 
 static const struct drm_flip_helper_funcs intel_flip_funcs = {
@@ -2430,6 +2541,12 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
+	if (!drm_async_gpu) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+		intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+		return;
+	}
+
 	mutex_lock(&dev->struct_mutex);
 
 	list_for_each_entry(intel_flip, &flips, base.list) {
-- 
1.7.8.6

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

  parent reply	other threads:[~2012-11-16 14:22 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
2012-11-16 14:22 ` [PATCH 01/13] drm/i915: Unstatic i915_gem_check_olr() ville.syrjala
2012-11-16 14:22 ` [PATCH 02/13] drm/i915: Refactor atomic flip code ville.syrjala
2012-11-16 14:22 ` [PATCH 03/13] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips ville.syrjala
2012-11-16 14:22 ` [PATCH 04/13] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
2012-11-16 14:22 ` [PATCH 05/13] drm/i915: Make a copy of the calculated plane regs ville.syrjala
2012-11-16 14:22 ` [PATCH 06/13] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
2012-11-16 14:22 ` [PATCH 07/13] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled ville.syrjala
2012-11-16 14:22 ` [PATCH 08/13] drm/i915: Add pin count trace point ville.syrjala
2012-11-16 14:22 ` [PATCH 09/13] drm/i915: Add trace points for flip queue length ville.syrjala
2012-11-16 14:22 ` ville.syrjala [this message]
2012-11-16 14:22 ` [PATCH 11/13] drm/i915: Add some timing debugs to atomic flips ville.syrjala
2012-11-16 14:22 ` [PATCH 12/13] drm/i915: Add post flush DSL readout for surflive debug ville.syrjala
2012-11-16 14:22 ` [PATCH 13/13] drm/i915: Add trace point for atomic flip vblank evade ville.syrjala

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=1353075745-30115-11-git-send-email-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --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.