All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2)
@ 2012-11-16 14:22 ville.syrjala
  2012-11-16 14:22 ` [PATCH 01/13] drm/i915: Unstatic i915_gem_check_olr() ville.syrjala
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

Here's my second attempt at making atomic page flips synchronize with the
GPU in a non-blocking manner.

What the code does by default is grap the last_write_seqno from the object,
call intel_gem_check_olr() on it, perform the lazy coherency check, and
if the seqno still hasn't passed it'll enable the irq and let that sort
things out. Now, I'm not sure if the call to intel_gem_check_olr() is even
necessary in practice, or can I just go on to checking the seqno directly.

With some earlier patches I was seeing an occasional glitch on my screen,
and so I tried out a few different variations (always adding a new request
to the ring and forcing a GPU cache flush), and for now I left that code
in there under a bunch of ifdefs. The glitch was probably caused by
committing the wrong register values to the hardware, and patch 05/13
should fix that. I haven't seen any issues for a while now.

The real meat is at the beginning of the patch set, and the second half
contains just debugging aids.

Oh, and I rebased the whole thing on top of drm-intel-nightly yesterday. The
haswell changes gave me a bit of grief, but I think I managed to preserve all
of them, and still make the atomic stuff work. But I haven't actually tried
running it on hsw hardware.

Besides my own tests, I also gave Ander's nuclear-pageflip branch of weston [1]
a go on top of this stuff. Seems to be working quite nicely so far. Now I just
need a working browser and sloppy focus, and I can ditch X ;)

As usual my git tree [2] has the whole set for easier consumption.

[1] https://github.com/anderco/weston/tree/nuclear-pageflip
[2] https://gitorious.org/vsyrjala/linux/commits/drm_atomic_21

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 01/13] drm/i915: Unstatic i915_gem_check_olr()
  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 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 02/13] drm/i915: Refactor atomic flip code ville.syrjala
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Atomic code might need i915_gem_check_olr().

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |    1 +
 drivers/gpu/drm/i915/i915_gem.c |    2 +-
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0ce1392..8805a07 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1463,6 +1463,7 @@ void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring);
 int __must_check i915_gem_check_wedge(struct drm_i915_private *dev_priv,
 				      bool interruptible);
+int i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno);
 
 void i915_gem_reset(struct drm_device *dev);
 void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a2f1b86..5158461 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -972,7 +972,7 @@ i915_gem_check_wedge(struct drm_i915_private *dev_priv,
  * Compare seqno against outstanding lazy request. Emit a request if they are
  * equal.
  */
-static int
+int
 i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
 {
 	int ret;
-- 
1.7.8.6

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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/13] drm/i915: Refactor atomic flip code
  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 ` 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
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Collect the part which takes care of issuing the flips to a new
function. This makes the following patch nicer to look at.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   37 ++++++++++++++++++++--------------
 1 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 7a7695b..33357ec 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2075,15 +2075,35 @@ static void intel_flip_fini(struct drm_device *dev)
 	drm_flip_driver_fini(&dev_priv->flip_driver);
 }
 
+static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
+					struct intel_crtc *intel_crtc,
+					struct list_head *flips)
+{
+	if (!intel_crtc->active) {
+		drm_flip_driver_complete_flips(&dev_priv->flip_driver, flips);
+		return;
+	}
+
+	drm_flip_driver_prepare_flips(&dev_priv->flip_driver, flips);
+
+	local_irq_disable();
+
+	intel_pipe_vblank_evade(&intel_crtc->base);
+
+	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, flips);
+
+	local_irq_enable();
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_file_private *file_priv = state->file->driver_priv;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
 	LIST_HEAD(flips);
 	int i;
-	bool pipe_enabled = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe))->active;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &state->crtc[i];
@@ -2189,20 +2209,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
-	if (!pipe_enabled) {
-		drm_flip_driver_complete_flips(&dev_priv->flip_driver, &flips);
-		return;
-	}
-
-	drm_flip_driver_prepare_flips(&dev_priv->flip_driver, &flips);
-
-	local_irq_disable();
-
-	intel_pipe_vblank_evade(intel_get_crtc_for_pipe(dev, pipe));
-
-	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, &flips);
-
-	local_irq_enable();
+	intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
 }
 
 void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/13] drm/i915: Implement a non-blocking GPU synchronization mechanism for atomic page flips
  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 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 04/13] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

After the atomic flip has been split up into individual flip requests
for each scanout engine, put each such request into a FIFO. Then for
each flip request add new request to the ring(s) in order to get an
interrupt once the GPU has finished whatever it was doing with the
new front buffer. Once the flip requests associated with the same
atomic flip and the same pipe at the head of the queue are ready,
pull them from the queue and issue the flips to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |    8 ++
 drivers/gpu/drm/i915/i915_irq.c     |    2 +
 drivers/gpu/drm/i915/intel_atomic.c |  233 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h    |    1 +
 4 files changed, 240 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8805a07..8aaf0ce 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -920,6 +920,14 @@ typedef struct drm_i915_private {
 	struct i915_dri1_state dri1;
 
 	struct drm_flip_driver flip_driver;
+
+	struct {
+		struct list_head list;
+		spinlock_t lock;
+		struct work_struct work;
+		struct workqueue_struct *wq;
+		unsigned int next_flip_seq;
+	} flip;
 } drm_i915_private_t;
 
 /* Iterate over initialised rings */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 74b6f5f..441306d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -348,6 +348,8 @@ static void notify_ring(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	intel_atomic_notify_ring(dev, ring);
+
 	if (ring->obj == NULL)
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 33357ec..04a20c5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -30,6 +30,10 @@
 
 #include "intel_drv.h"
 
+#define USE_WRITE_SEQNO
+#define USE_OLR
+//#define FORCE_CACHE_FLUSH
+
 struct intel_flip {
 	struct drm_flip base;
 	u32 vbl_count;
@@ -42,6 +46,9 @@ struct intel_flip {
 	struct drm_pending_atomic_event *event;
 	uint32_t old_fb_id;
 	struct list_head pending_head;
+	struct intel_ring_buffer *ring;
+	u32 seqno;
+	unsigned int flip_seq;
 };
 
 struct intel_plane_state {
@@ -801,6 +808,7 @@ static int pin_fbs(struct drm_device *dev,
 		   struct intel_atomic_state *s)
 {
 	int i, ret;
+	bool nonblock = s->flags & DRM_MODE_ATOMIC_NONBLOCK;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &s->crtc[i];
@@ -816,7 +824,7 @@ static int pin_fbs(struct drm_device *dev,
 		obj = to_intel_framebuffer(crtc->fb)->obj;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL);
 		mutex_unlock(&dev->struct_mutex);
 
 		if (ret)
@@ -839,7 +847,7 @@ static int pin_fbs(struct drm_device *dev,
 		obj = to_intel_framebuffer(plane->fb)->obj;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+		ret = intel_pin_and_fence_fb_obj(dev, obj, nonblock ? obj->ring : NULL);
 		mutex_unlock(&dev->struct_mutex);
 
 		if (ret)
@@ -2040,6 +2048,8 @@ static const struct drm_flip_driver_funcs intel_flip_driver_funcs = {
 	.flush = intel_flip_driver_flush,
 };
 
+static void intel_atomic_process_flips_work(struct work_struct *work);
+
 static void intel_flip_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2058,6 +2068,11 @@ static void intel_flip_init(struct drm_device *dev)
 	list_for_each_entry(intel_plane, &dev->mode_config.plane_list, base.head)
 		drm_flip_helper_init(&intel_plane->flip_helper,
 				     &dev_priv->flip_driver, &intel_flip_funcs);
+
+	INIT_LIST_HEAD(&dev_priv->flip.list);
+	spin_lock_init(&dev_priv->flip.lock);
+	INIT_WORK(&dev_priv->flip.work, intel_atomic_process_flips_work);
+	dev_priv->flip.wq = create_singlethread_workqueue("intel_flip");
 }
 
 static void intel_flip_fini(struct drm_device *dev)
@@ -2075,6 +2090,46 @@ static void intel_flip_fini(struct drm_device *dev)
 	drm_flip_driver_fini(&dev_priv->flip_driver);
 }
 
+static bool intel_atomic_postpone_flip(struct intel_flip *intel_flip)
+{
+	struct intel_ring_buffer *ring = intel_flip->ring;
+	int ret;
+
+#ifdef FORCE_CACHE_FLUSH
+	/* Unconditionally force add_request to emit a full flush. */
+	ring->gpu_caches_dirty = true;
+#endif
+
+#ifdef USE_OLR
+	ret = i915_gem_check_olr(ring, intel_flip->seqno);
+	if (WARN_ON(ret)) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+
+	if (i915_seqno_passed(ring->get_seqno(ring, true), intel_flip->seqno)) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+#endif
+
+	if (WARN_ON(!ring->irq_get(ring))) {
+		intel_flip->ring = NULL;
+		return false;
+	}
+
+#ifndef USE_OLR
+	ret = i915_add_request(ring, NULL, &intel_flip->seqno);
+	if (WARN_ON(ret)) {
+		ring->irq_put(ring);
+		intel_flip->ring = NULL;
+		return false;
+	}
+#endif
+
+	return true;
+}
+
 static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 					struct intel_crtc *intel_crtc,
 					struct list_head *flips)
@@ -2095,15 +2150,120 @@ static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 	local_irq_enable();
 }
 
+static  bool intel_atomic_flips_ready(struct drm_device *dev, unsigned int flip_seq)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+
+	/* check if all flips w/ same flip_seq are ready */
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		if (intel_flip->flip_seq != flip_seq)
+			break;
+
+		if (intel_flip->ring)
+			return false;
+	}
+
+	return true;
+}
+
+static void intel_atomic_process_flips_work(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, flip.work);
+	struct drm_device *dev = dev_priv->dev;
+
+	for (;;) {
+		struct intel_flip *intel_flip, *next;
+		unsigned int flip_seq;
+		struct intel_crtc *intel_crtc;
+		LIST_HEAD(flips);
+		unsigned long flags;
+
+		if (list_empty(&dev_priv->flip.list))
+			return;
+
+		spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+		intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list);
+		flip_seq = intel_flip->flip_seq;
+		intel_crtc = to_intel_crtc(intel_flip->crtc);
+
+		if (intel_atomic_flips_ready(dev, flip_seq)) {
+			list_for_each_entry_safe(intel_flip, next, &dev_priv->flip.list, base.list) {
+				if (intel_flip->flip_seq != flip_seq)
+					break;
+				list_move_tail(&intel_flip->base.list, &flips);
+			}
+		}
+
+		spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+
+		if (list_empty(&flips))
+			return;
+
+		mutex_lock(&dev->mode_config.mutex);
+		intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+		mutex_unlock(&dev->mode_config.mutex);
+	}
+}
+
+static void intel_atomic_check_flips_ready(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+
+	if (list_empty(&dev_priv->flip.list))
+		return;
+
+	intel_flip = list_first_entry(&dev_priv->flip.list, struct intel_flip, base.list);
+	if (intel_atomic_flips_ready(dev, intel_flip->flip_seq))
+		queue_work(dev_priv->flip.wq, &dev_priv->flip.work);
+}
+
+void intel_atomic_notify_ring(struct drm_device *dev,
+			      struct intel_ring_buffer *ring)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+	unsigned long flags;
+	u32 seqno;
+
+	if (list_empty(&dev_priv->flip.list))
+		return;
+
+	seqno = ring->get_seqno(ring, false);
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		if (ring != intel_flip->ring)
+			continue;
+
+		if (i915_seqno_passed(seqno, intel_flip->seqno)) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+	}
+
+	intel_atomic_check_flips_ready(dev);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_file_private *file_priv = state->file->driver_priv;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
 	LIST_HEAD(flips);
 	int i;
+	/* FIXME treat flips for all pipes as one set for GPU sync */
+	unsigned int flip_seq = dev_priv->flip.next_flip_seq++;
+	struct intel_flip *intel_flip, *next;
+	unsigned long flags;
+	struct intel_ring_buffer *ring;
+	unsigned int rings_mask = 0;
 
 	for (i = 0; i < dev->mode_config.num_crtc; i++) {
 		struct intel_crtc_state *st = &state->crtc[i];
@@ -2122,6 +2282,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_crtc->flip_helper);
 
+		intel_flip->flip_seq = flip_seq;
+
 		if (st->event) {
 			intel_flip->event = st->event;
 			st->event = NULL;
@@ -2134,6 +2296,19 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		intel_flip->crtc = crtc;
 
+		if (crtc->fb) {
+			struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc->fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+#ifdef USE_WRITE_SEQNO
+			intel_flip->seqno = obj->last_write_seqno;
+#else
+			intel_flip->seqno = obj->last_read_seqno;
+#endif
+			intel_flip->ring = obj->ring;
+			mutex_unlock(&dev->struct_mutex);
+		}
+
 		/* update primary_disabled befoer calc_plane() */
 		intel_crtc->primary_disabled = st->primary_disabled;
 
@@ -2177,6 +2352,8 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 		drm_flip_init(&intel_flip->base, &intel_plane->flip_helper);
 
+		intel_flip->flip_seq = flip_seq;
+
 		if (st->event) {
 			intel_flip->event = st->event;
 			st->event = NULL;
@@ -2190,6 +2367,19 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		intel_flip->crtc = intel_get_crtc_for_pipe(dev, pipe);
 		intel_flip->plane = plane;
 
+		if (plane->fb) {
+			struct drm_i915_gem_object *obj = to_intel_framebuffer(plane->fb)->obj;
+
+			mutex_lock(&dev->struct_mutex);
+#ifdef USE_WRITE_SEQNO
+			intel_flip->seqno = obj->last_write_seqno;
+#else
+			intel_flip->seqno = obj->last_read_seqno;
+#endif
+			intel_flip->ring = obj->ring;
+			mutex_unlock(&dev->struct_mutex);
+		}
+
 		intel_plane->calc(plane, plane->fb, &st->coords);
 
 		if (st->old.fb)
@@ -2209,7 +2399,42 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (list_empty(&flips))
 		return;
 
-	intel_atomic_schedule_flips(dev_priv, intel_crtc, &flips);
+	mutex_lock(&dev->struct_mutex);
+
+	list_for_each_entry(intel_flip, &flips, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (!ring)
+			continue;
+
+		if (intel_atomic_postpone_flip(intel_flip))
+			rings_mask |= intel_ring_flag(ring);
+	}
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list)
+		list_move_tail(&intel_flip->base.list, &dev_priv->flip.list);
+
+	/* if no rings are involved, we can avoid checking seqnos */
+	if (rings_mask == 0)
+		intel_atomic_check_flips_ready(dev);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	if (rings_mask == 0)
+		return;
+
+	/*
+	 * Double check to catch cases where the irq
+	 * fired before the flip was placed onto flip.list.
+	 */
+	for_each_ring(ring, dev_priv, i) {
+		if (rings_mask & intel_ring_flag(ring))
+			intel_atomic_notify_ring(dev, ring);
+	}
 }
 
 void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8eabf40..319aac8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -722,6 +722,7 @@ extern void intel_atomic_fini(struct drm_device *dev);
 extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *file);
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
+extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/13] drm/i915: Release all atomic flips when GPU hangs
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (2 preceding siblings ...)
  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 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 05/13] drm/i915: Make a copy of the calculated plane regs ville.syrjala
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

If the GPU hangs, release all pending atomic flips from the queue.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c     |    1 +
 drivers/gpu/drm/i915/intel_atomic.c |   29 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |    1 +
 3 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 441306d..f70d2b1 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1452,6 +1452,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
 		 */
 		for_each_ring(ring, dev_priv, i)
 			wake_up_all(&ring->irq_queue);
+		intel_atomic_wedged(dev);
 	}
 
 	queue_work(dev_priv->wq, &dev_priv->error_work);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 04a20c5..7a0e315 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2250,6 +2250,30 @@ void intel_atomic_notify_ring(struct drm_device *dev,
 	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 }
 
+void intel_atomic_wedged(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_flip *intel_flip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+
+	list_for_each_entry(intel_flip, &dev_priv->flip.list, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (ring) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+	}
+
+	/* all flips are "ready" so no need to check with intel_atomic_flips_ready() */
+	if (!list_empty(&dev_priv->flip.list))
+		queue_work(dev_priv->flip.wq, &dev_priv->flip.work);
+
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
+}
+
 static void atomic_pipe_commit(struct drm_device *dev,
 			       struct intel_atomic_state *state,
 			       int pipe)
@@ -2427,6 +2451,11 @@ static void atomic_pipe_commit(struct drm_device *dev,
 	if (rings_mask == 0)
 		return;
 
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		intel_atomic_wedged(dev);
+		return;
+	}
+
 	/*
 	 * Double check to catch cases where the irq
 	 * fired before the flip was placed onto flip.list.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 319aac8..617ba4d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -723,6 +723,7 @@ extern void intel_atomic_free_events(struct drm_device *dev, struct drm_file *fi
 extern void intel_atomic_handle_vblank(struct drm_device *dev, int pipe);
 extern void intel_atomic_clear_flips(struct drm_crtc *crtc);
 extern void intel_atomic_notify_ring(struct drm_device *dev, struct intel_ring_buffer *ring);
+extern void intel_atomic_wedged(struct drm_device *dev);
 
 extern void intel_enable_primary(struct drm_crtc *crtc);
 extern void intel_disable_primary(struct drm_crtc *crtc);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/13] drm/i915: Make a copy of the calculated plane regs
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (3 preceding siblings ...)
  2012-11-16 14:22 ` [PATCH 04/13] drm/i915: Release all atomic flips when GPU hangs ville.syrjala
@ 2012-11-16 14:22 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 06/13] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

The register values are computed when the flip ioctl is issued, and
they're used only after we've waited for the GPU to finish rendering.
The computed values are store in the intel_crtc and intel_plane structs,
so issuing another flip before the previous one has been fully completed
would clobber those stored registers. Fix the problem by making a copy
of the calculated register values inside the intel_flip structure. The
copy is then used when it's time to commit the registers to the hardware.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |    4 +++-
 drivers/gpu/drm/i915/intel_atomic.c  |    8 ++++++--
 drivers/gpu/drm/i915/intel_display.c |   14 ++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |    2 +-
 drivers/gpu/drm/i915/intel_sprite.c  |   24 ++++++++++++------------
 5 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8aaf0ce..91e2dc6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -247,6 +247,8 @@ struct drm_i915_error_state {
 	struct intel_display_error_state *display;
 };
 
+struct intel_plane_regs;
+
 struct drm_i915_display_funcs {
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
@@ -278,7 +280,7 @@ struct drm_i915_display_funcs {
 			    int x, int y);
 	int (*calc_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			  int x, int y);
-	void (*commit_plane)(struct drm_crtc *crtc);
+	void (*commit_plane)(struct drm_crtc *crtc, const struct intel_plane_regs *regs);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 7a0e315..0aa8c93 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -49,6 +49,8 @@ struct intel_flip {
 	struct intel_ring_buffer *ring;
 	u32 seqno;
 	unsigned int flip_seq;
+	/* FIXME need cursor regs too */
+	struct intel_plane_regs regs;
 };
 
 struct intel_plane_state {
@@ -1988,11 +1990,11 @@ static bool intel_flip_flip(struct drm_flip *flip,
 		struct drm_plane *plane = intel_flip->plane;
 		struct intel_plane *intel_plane = to_intel_plane(plane);
 
-		intel_plane->commit(plane);
+		intel_plane->commit(plane, &intel_flip->regs);
 	} else {
 		struct drm_i915_private *dev_priv = dev->dev_private;
 
-		dev_priv->display.commit_plane(crtc);
+		dev_priv->display.commit_plane(crtc, &intel_flip->regs);
 	}
 
 	if (intel_flip->has_cursor)
@@ -2339,6 +2341,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		/* should already be checked so can't fail */
 		/* FIXME refactor the failing parts? */
 		dev_priv->display.calc_plane(crtc, crtc->fb, crtc->x, crtc->y);
+		intel_flip->regs = intel_crtc->primary_regs;
 
 		if (st->cursor_dirty) {
 			intel_flip->has_cursor = true;
@@ -2405,6 +2408,7 @@ static void atomic_pipe_commit(struct drm_device *dev,
 		}
 
 		intel_plane->calc(plane, plane->fb, &st->coords);
+		intel_flip->regs = intel_plane->regs;
 
 		if (st->old.fb)
 			intel_flip->old_fb_id = st->old.fb->base.id;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7537a2c..48eeed5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2030,13 +2030,13 @@ unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
 	return tile_rows * pitch * 8 + tiles * 4096;
 }
 
-static void intel_commit_plane(struct drm_crtc *crtc)
+static void intel_commit_plane(struct drm_crtc *crtc,
+			       const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int plane = intel_crtc->plane;
-	const struct intel_plane_regs *regs = &intel_crtc->primary_regs;
 
 	I915_WRITE(DSPCNTR(plane), regs->cntr);
 	I915_WRITE(DSPSTRIDE(plane), regs->stride);
@@ -2153,15 +2153,16 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 			     int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = i9xx_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
@@ -2257,15 +2258,16 @@ static int ironlake_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *
 				 int x, int y)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int ret;
 
 	ret = ironlake_calc_plane(crtc, fb, x, y);
 	if (ret)
 		return ret;
 
-	intel_commit_plane(crtc);
+	intel_commit_plane(crtc, &intel_crtc->primary_regs);
 
-	POSTING_READ(DSPCNTR(to_intel_crtc(crtc)->plane));
+	POSTING_READ(DSPCNTR(intel_crtc->plane));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 617ba4d..9771a10 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -274,7 +274,7 @@ struct intel_plane {
 	void (*calc)(struct drm_plane *plane, struct drm_framebuffer *fb,
 		     const struct intel_plane_coords *clip);
 	void (*prepare)(struct drm_plane *plane);
-	void (*commit)(struct drm_plane *plane);
+	void (*commit)(struct drm_plane *plane, const struct intel_plane_regs *regs);
 	struct intel_plane_regs regs;
 	struct drm_flip_helper flip_helper;
 };
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ce3b950..d960e19 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -300,13 +300,13 @@ ivb_calc_plane(struct drm_plane *plane,
 }
 
 static void
-ivb_commit_plane(struct drm_plane *plane)
+ivb_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(SPRKEYVAL(pipe), regs->keyval);
 	I915_WRITE(SPRKEYMAX(pipe), regs->keymaxval);
@@ -371,7 +371,7 @@ ivb_update_plane(struct drm_plane *plane,
 
 	ivb_calc_plane(plane, fb, coords);
 	ivb_prepare_plane(plane);
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -387,7 +387,7 @@ ivb_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~SPRITE_ENABLE;
 	/* Can't leave the scaler enabled... */
 	regs->scale = 0;
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRSURF(pipe));
 
 	dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
@@ -413,7 +413,7 @@ ivb_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= SPRITE_SOURCE_KEY;
 
-	ivb_commit_plane(plane);
+	ivb_commit_plane(plane, regs);
 	POSTING_READ(SPRKEYMSK(intel_plane->pipe));
 
 	return 0;
@@ -546,13 +546,13 @@ ilk_prepare_plane(struct drm_plane *plane)
 }
 
 static void
-ilk_commit_plane(struct drm_plane *plane)
+ilk_commit_plane(struct drm_plane *plane,
+		 const struct intel_plane_regs *regs)
 {
 	struct drm_device *dev = plane->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	int pipe = intel_plane->pipe;
-	const struct intel_plane_regs *regs = &intel_plane->regs;
 
 	I915_WRITE(DVSKEYVAL(pipe), regs->keyval);
 	I915_WRITE(DVSKEYMAX(pipe), regs->keymaxval);
@@ -579,7 +579,7 @@ ilk_update_plane(struct drm_plane *plane,
 
 	ilk_calc_plane(plane, fb, coords);
 	ilk_prepare_plane(plane);
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, &intel_plane->regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -595,7 +595,7 @@ ilk_disable_plane(struct drm_plane *plane)
 	regs->cntr &= ~DVS_ENABLE;
 	/* Disable the scaler */
 	regs->scale = 0;
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -627,7 +627,7 @@ intel_enable_primary(struct drm_crtc *crtc)
 	intel_update_fbc(dev);
 
 	regs->cntr = I915_READ(reg) | DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 }
 
 void
@@ -643,7 +643,7 @@ intel_disable_primary(struct drm_crtc *crtc)
 		return;
 
 	regs->cntr = I915_READ(reg) & ~DISPLAY_PLANE_ENABLE;
-	dev_priv->display.commit_plane(crtc);
+	dev_priv->display.commit_plane(crtc, regs);
 
 	intel_crtc->primary_disabled = true;
 	intel_update_fbc(dev);
@@ -668,7 +668,7 @@ ilk_update_colorkey(struct drm_plane *plane,
 	else if (key->flags & I915_SET_COLORKEY_SOURCE)
 		regs->cntr |= DVS_SOURCE_KEY;
 
-	ilk_commit_plane(plane);
+	ilk_commit_plane(plane, regs);
 	POSTING_READ(DVSKEYMSK(intel_plane->pipe));
 
 	return 0;
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/13] drm/i915: Clear pending flips in haswell_crtc_disable()
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (4 preceding siblings ...)
  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 ` 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
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 48eeed5..acd5aa0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3666,6 +3666,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 		encoder->disable(encoder);
 
 	intel_crtc_wait_for_pending_flips(crtc);
+	intel_atomic_clear_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
-- 
1.7.8.6

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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/13] drm/i915: Drop all flips waiting for the GPU when the CRTC is about to be disabled
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (5 preceding siblings ...)
  2012-11-16 14:22 ` [PATCH 06/13] drm/i915: Clear pending flips in haswell_crtc_disable() ville.syrjala
@ 2012-11-16 14:22 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 08/13] drm/i915: Add pin count trace point ville.syrjala
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   36 +++++++++++++++++++++++++++++++++++
 1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 0aa8c93..6bec72b 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2489,9 +2489,23 @@ void intel_atomic_handle_vblank(struct drm_device *dev, int pipe)
 void intel_atomic_clear_flips(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane;
+	struct intel_flip *intel_flip, *next;
 	int pipe = intel_crtc->pipe;
+	unsigned long flags;
+	LIST_HEAD(flips);
+
+	/*
+	 * If there are flips still waiting for the GPU, remove them
+	 * from the list, so that they won't be able to move over to
+	 * drm_flip_helpers' possession after we've called
+	 * drm_flip_helper_clear().
+	 */
+	spin_lock_irqsave(&dev_priv->flip.lock, flags);
+	list_cut_position(&flips, &dev_priv->flip.list, dev_priv->flip.list.prev);
+	spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 
 	drm_flip_helper_clear(&intel_crtc->flip_helper);
 
@@ -2499,4 +2513,26 @@ void intel_atomic_clear_flips(struct drm_crtc *crtc)
 		if (intel_plane->pipe == pipe)
 			drm_flip_helper_clear(&intel_plane->flip_helper);
 	}
+
+	/*
+	 * Drop all non-ready flips. Doing this after calling
+	 * drm_flip_helper_clear() maintaines the correct order
+	 * of completion events.
+	 */
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list) {
+		struct intel_ring_buffer *ring = intel_flip->ring;
+
+		if (ring) {
+			intel_flip->ring = NULL;
+			ring->irq_put(ring);
+		}
+
+		intel_flip_complete(&intel_flip->base);
+		/*
+		 * FIXME drm_flip_helper calls the following functions
+		 * from a workqueue. Perhaps we should do the same here?
+		 */
+		intel_flip_finish(&intel_flip->base);
+		intel_flip_cleanup(&intel_flip->base);
+	}
 }
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/13] drm/i915: Add pin count trace point
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (6 preceding siblings ...)
  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 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 09/13] drm/i915: Add trace points for flip queue length ville.syrjala
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

A new trace point for tracking changes to gem object pin count.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c   |    6 ++++++
 drivers/gpu/drm/i915/i915_trace.h |   19 +++++++++++++++++++
 2 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5158461..0bfc8af 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3466,6 +3466,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 	if (!obj->has_global_gtt_mapping && map_and_fenceable)
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, obj->pin_count + 1);
+
 	obj->pin_count++;
 	obj->pin_mappable |= map_and_fenceable;
 
@@ -3475,6 +3477,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 void
 i915_gem_object_unpin(struct drm_i915_gem_object *obj)
 {
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, obj->pin_count - 1);
+
 	BUG_ON(obj->pin_count == 0);
 	BUG_ON(obj->gtt_space == NULL);
 
@@ -3753,6 +3757,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	if (obj->phys_obj)
 		i915_gem_detach_phys_object(dev, obj);
 
+	trace_i915_gem_object_pin_count(obj, obj->pin_count, 0);
+
 	obj->pin_count = 0;
 	if (WARN_ON(i915_gem_object_unbind(obj) == -ERESTARTSYS)) {
 		bool was_interruptible;
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 3db4a68..44f8d40 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,25 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_gem_object_pin_count,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 pin_count_pre, u32 pin_count_post),
+	    TP_ARGS(obj, pin_count_pre, pin_count_post),
+
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, pin_count_pre)
+			     __field(u32, pin_count_post)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->pin_count_pre = pin_count_pre;
+			   __entry->pin_count_post = pin_count_post;
+			   ),
+
+	    TP_printk("obj=%p, pin_count=%u->%u", __entry->obj, __entry->pin_count_pre, __entry->pin_count_post)
+);
+
 TRACE_EVENT(i915_gem_object_create,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
 	    TP_ARGS(obj),
-- 
1.7.8.6

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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/13] drm/i915: Add trace points for flip queue length
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (7 preceding siblings ...)
  2012-11-16 14:22 ` [PATCH 08/13] drm/i915: Add pin count trace point ville.syrjala
@ 2012-11-16 14:22 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 10/13] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

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

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 91e2dc6..3a9a8a0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -929,6 +929,7 @@ typedef struct drm_i915_private {
 		struct work_struct work;
 		struct workqueue_struct *wq;
 		unsigned int next_flip_seq;
+		unsigned int queue_len;
 	} flip;
 } drm_i915_private_t;
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 44f8d40..f71e1b3 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,21 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_flip_queue_len,
+	    TP_PROTO(unsigned int queue_len),
+	    TP_ARGS(queue_len),
+
+	    TP_STRUCT__entry(
+			     __field(u32, queue_len)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->queue_len = queue_len;
+			   ),
+
+	    TP_printk("queue_len=%u", __entry->queue_len)
+);
+
 TRACE_EVENT(i915_gem_object_pin_count,
 	    TP_PROTO(struct drm_i915_gem_object *obj, u32 pin_count_pre, u32 pin_count_post),
 	    TP_ARGS(obj, pin_count_pre, pin_count_post),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 6bec72b..f2e6d88 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -2195,9 +2195,12 @@ static void intel_atomic_process_flips_work(struct work_struct *work)
 				if (intel_flip->flip_seq != flip_seq)
 					break;
 				list_move_tail(&intel_flip->base.list, &flips);
+				dev_priv->flip.queue_len--;
 			}
 		}
 
+		trace_i915_flip_queue_len(dev_priv->flip.queue_len);
+
 		spin_unlock_irqrestore(&dev_priv->flip.lock, flags);
 
 		if (list_empty(&flips))
@@ -2441,8 +2444,12 @@ static void atomic_pipe_commit(struct drm_device *dev,
 
 	spin_lock_irqsave(&dev_priv->flip.lock, flags);
 
-	list_for_each_entry_safe(intel_flip, next, &flips, base.list)
+	list_for_each_entry_safe(intel_flip, next, &flips, base.list) {
 		list_move_tail(&intel_flip->base.list, &dev_priv->flip.list);
+		dev_priv->flip.queue_len++;
+	}
+
+	trace_i915_flip_queue_len(dev_priv->flip.queue_len);
 
 	/* if no rings are involved, we can avoid checking seqnos */
 	if (rings_mask == 0)
-- 
1.7.8.6

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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/13] HACK: drm/i915: Make non-blocking GPU synchronization optional
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (8 preceding siblings ...)
  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
  2012-11-16 14:22 ` [PATCH 11/13] drm/i915: Add some timing debugs to atomic flips ville.syrjala
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/13] drm/i915: Add some timing debugs to atomic flips
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (9 preceding siblings ...)
  2012-11-16 14:22 ` [PATCH 10/13] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
@ 2012-11-16 14:22 ` 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
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

---
 drivers/gpu/drm/i915/intel_atomic.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 170ac6f..c6531b0 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -35,6 +35,7 @@
 //#define FORCE_CACHE_FLUSH
 
 //#define SURFLIVE_DEBUG
+//#define FLIP_TIME_DEBUG
 
 struct intel_flip {
 	struct drm_flip base;
@@ -1842,6 +1843,10 @@ static void intel_flip_cleanup(struct drm_flip *flip)
 	kfree(intel_flip);
 }
 
+#ifdef FLIP_TIME_DEBUG
+static ktime_t tstart, tend, tdiff;
+#endif
+
 static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 {
 	struct drm_i915_private *dev_priv =
@@ -1849,6 +1854,13 @@ static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 
 	/* Flush posted writes */
 	I915_READ(PIPEDSL(PIPE_A));
+
+#ifdef FLIP_TIME_DEBUG
+	tend = ktime_get();
+	tdiff = ktime_sub(tend, tstart);
+	if (ktime_to_ns(tdiff) >= 10000ULL)
+		DRM_DEBUG_KMS("**** flip took %llu nsec ****\n", ktime_to_ns(tdiff));
+#endif
 }
 
 static bool intel_have_new_frmcount(struct drm_device *dev)
@@ -2258,6 +2270,9 @@ static void intel_atomic_schedule_flips(struct drm_i915_private *dev_priv,
 
 	intel_pipe_vblank_evade(&intel_crtc->base);
 
+#ifdef FLIP_TIME_DEBUG
+	tstart = ktime_get();
+#endif
 	drm_flip_driver_schedule_flips(&dev_priv->flip_driver, flips);
 
 	local_irq_enable();
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 12/13] drm/i915: Add post flush DSL readout for surflive debug
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (10 preceding siblings ...)
  2012-11-16 14:22 ` [PATCH 11/13] drm/i915: Add some timing debugs to atomic flips ville.syrjala
@ 2012-11-16 14:22 ` ville.syrjala
  2012-11-16 14:22 ` [PATCH 13/13] drm/i915: Add trace point for atomic flip vblank evade ville.syrjala
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_trace.h   |   19 +++++++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |    4 ++++
 2 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 754a204..fb35edd 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,25 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_flush,
+	    TP_PROTO(u32 dsl0, u32 dsl1, u32 dsl2),
+	    TP_ARGS(dsl0, dsl1, dsl2),
+
+	    TP_STRUCT__entry(
+			     __field(u32, dsl0)
+			     __field(u32, dsl1)
+			     __field(u32, dsl2)
+			     ),
+	    TP_fast_assign(
+			   __entry->dsl0 = dsl0;
+			   __entry->dsl1 = dsl1;
+			   __entry->dsl2 = dsl2;
+			   ),
+
+	    TP_printk("dsl(0)=%u dsl(1)=%u dsl(2)=%u", __entry->dsl0, __entry->dsl1, __entry->dsl2)
+);
+
+
 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),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index c6531b0..945ba75 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1855,6 +1855,10 @@ static void intel_flip_driver_flush(struct drm_flip_driver *driver)
 	/* Flush posted writes */
 	I915_READ(PIPEDSL(PIPE_A));
 
+#ifdef SURFLIVE_DEBUG
+	trace_i915_atomic_flush(I915_READ(PIPEDSL(0)), I915_READ(PIPEDSL(1)), I915_READ(PIPEDSL(2)));
+#endif
+
 #ifdef FLIP_TIME_DEBUG
 	tend = ktime_get();
 	tdiff = ktime_sub(tend, tstart);
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 13/13] drm/i915: Add trace point for atomic flip vblank evade
  2012-11-16 14:22 [PATCH 00/13] drm/i915: Non-blocking GPU synchronization for atomic page flips (v2) ville.syrjala
                   ` (11 preceding siblings ...)
  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 ` ville.syrjala
  12 siblings, 0 replies; 14+ messages in thread
From: ville.syrjala @ 2012-11-16 14:22 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

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

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_trace.h   |   18 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_atomic.c |    2 ++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index fb35edd..2b529f2 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -16,6 +16,24 @@
 
 /* object tracking */
 
+TRACE_EVENT(i915_atomic_evade,
+	    TP_PROTO(u32 dsl_min, u32 dsl_max, u32 dsl),
+	    TP_ARGS(dsl_min, dsl_max, dsl),
+
+	    TP_STRUCT__entry(
+			     __field(u32, dsl_min)
+			     __field(u32, dsl_max)
+			     __field(u32, dsl)
+			     ),
+	    TP_fast_assign(
+			   __entry->dsl_min = dsl_min;
+			   __entry->dsl_max = dsl_max;
+			   __entry->dsl = dsl;
+			   ),
+
+	    TP_printk("dsl_min=%u dsl_max=%u dsl=%u", __entry->dsl_min, __entry->dsl_max, __entry->dsl)
+);
+
 TRACE_EVENT(i915_atomic_flush,
 	    TP_PROTO(u32 dsl0, u32 dsl1, u32 dsl2),
 	    TP_ARGS(dsl0, dsl1, dsl2),
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 945ba75..69827a8 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -1950,6 +1950,8 @@ static void intel_pipe_vblank_evade(struct drm_crtc *crtc)
 		intel_crtc->vbl_received = false;
 
 		val = I915_READ(PIPEDSL(pipe));
+
+		trace_i915_atomic_evade(min, max, val);
 	}
 
 	if (vblank_ref)
-- 
1.7.8.6

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-11-16 14:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 10/13] HACK: drm/i915: Make non-blocking GPU synchronization optional ville.syrjala
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

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.