All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm/i915: Introduce for_each_ring() macro
@ 2012-05-11 13:29 Chris Wilson
  2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Chris Wilson @ 2012-05-11 13:29 UTC (permalink / raw)
  To: intel-gfx

In many places we wish to iterate over the rings associated with the
GPU, so refactor them to use a common macro.

Along the way, there are a few code removals that should be side-effect
free and some rearrangement which should only have a cosmetic impact,
such as error-state.

v2: Pull in a couple of suggestions from Ben and Daniel for
intel_ring_initialized() and not removing the warning (just moving them
to a new home, closer to the error).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |    9 ++--
 drivers/gpu/drm/i915/i915_drv.c         |   10 ++---
 drivers/gpu/drm/i915/i915_drv.h         |    9 ++--
 drivers/gpu/drm/i915/i915_gem.c         |   39 ++++++++---------
 drivers/gpu/drm/i915/i915_gem_evict.c   |   14 +++----
 drivers/gpu/drm/i915/i915_irq.c         |   69 +++++++++++++------------------
 drivers/gpu/drm/i915/intel_pm.c         |    5 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |    6 +++
 8 files changed, 76 insertions(+), 85 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 950f72a..eb2b3c2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -699,6 +699,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
 	struct drm_device *dev = error_priv->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_error_state *error = error_priv->error;
+	struct intel_ring_buffer *ring;
 	int i, j, page, offset, elt;
 
 	if (!error) {
@@ -706,7 +707,6 @@ static int i915_error_state(struct seq_file *m, void *unused)
 		return 0;
 	}
 
-
 	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
 		   error->time.tv_usec);
 	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
@@ -722,11 +722,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
 		seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
 	}
 
-	i915_ring_error_state(m, dev, error, RCS);
-	if (HAS_BLT(dev))
-		i915_ring_error_state(m, dev, error, BCS);
-	if (HAS_BSD(dev))
-		i915_ring_error_state(m, dev, error, VCS);
+	for_each_ring(ring, dev_priv, i)
+		i915_ring_error_state(m, dev, error, i);
 
 	if (error->active_bo)
 		print_error_buffers(m, "Active",
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 5898be9..3947804 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -893,15 +893,15 @@ int i915_reset(struct drm_device *dev)
 	 */
 	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
 			!dev_priv->mm.suspended) {
+		struct intel_ring_buffer *ring;
+		int i;
+
 		dev_priv->mm.suspended = 0;
 
 		i915_gem_init_swizzling(dev);
 
-		dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
-		if (HAS_BSD(dev))
-		    dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
-		if (HAS_BLT(dev))
-		    dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
+		for_each_ring(ring, dev_priv, i)
+			ring->init(ring);
 
 		i915_gem_init_ppgtt(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 83a557c..11c7a6a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -410,9 +410,7 @@ typedef struct drm_i915_private {
 #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
 	struct timer_list hangcheck_timer;
 	int hangcheck_count;
-	uint32_t last_acthd;
-	uint32_t last_acthd_bsd;
-	uint32_t last_acthd_blt;
+	uint32_t last_acthd[I915_NUM_RINGS];
 	uint32_t last_instdone;
 	uint32_t last_instdone1;
 
@@ -820,6 +818,11 @@ typedef struct drm_i915_private {
 	struct drm_property *force_audio_property;
 } drm_i915_private_t;
 
+/* Iterate over initialised rings */
+#define for_each_ring(ring__, dev_priv__, i__) \
+	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
+		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
+
 enum hdmi_force_audio {
 	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
 	HDMI_AUDIO_OFF,			/* force turn off HDMI audio */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 44a5f24..6d2180c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1655,10 +1655,11 @@ void i915_gem_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
+	struct intel_ring_buffer *ring;
 	int i;
 
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]);
+	for_each_ring(ring, dev_priv, i)
+		i915_gem_reset_ring_lists(dev_priv, ring);
 
 	/* Remove anything from the flushing lists. The GPU cache is likely
 	 * to be lost on reset along with the data, so simply move the
@@ -1763,10 +1764,11 @@ void
 i915_gem_retire_requests(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	int i;
 
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		i915_gem_retire_requests_ring(&dev_priv->ring[i]);
+	for_each_ring(ring, dev_priv, i)
+		i915_gem_retire_requests_ring(ring);
 }
 
 static void
@@ -1774,6 +1776,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 {
 	drm_i915_private_t *dev_priv;
 	struct drm_device *dev;
+	struct intel_ring_buffer *ring;
 	bool idle;
 	int i;
 
@@ -1793,9 +1796,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	 * objects indefinitely.
 	 */
 	idle = true;
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		struct intel_ring_buffer *ring = &dev_priv->ring[i];
-
+	for_each_ring(ring, dev_priv, i) {
 		if (!list_empty(&ring->gpu_write_list)) {
 			struct drm_i915_gem_request *request;
 			int ret;
@@ -2137,13 +2138,18 @@ static int i915_ring_idle(struct intel_ring_buffer *ring)
 int i915_gpu_idle(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	int ret, i;
 
 	/* Flush everything onto the inactive list. */
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		ret = i915_ring_idle(&dev_priv->ring[i]);
+	for_each_ring(ring, dev_priv, i) {
+		ret = i915_ring_idle(ring);
 		if (ret)
 			return ret;
+
+		/* Is the device fubar? */
+		if (WARN_ON(!list_empty(&ring->gpu_write_list)))
+			return -EBUSY;
 	}
 
 	return 0;
@@ -3463,9 +3469,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
 		/* GFX_MODE is per-ring on gen7+ */
 	}
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		ring = &dev_priv->ring[i];
-
+	for_each_ring(ring, dev_priv, i) {
 		if (INTEL_INFO(dev)->gen >= 7)
 			I915_WRITE(RING_MODE_GEN7(ring),
 				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
@@ -3581,10 +3585,11 @@ void
 i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	int i;
 
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
+	for_each_ring(ring, dev_priv, i)
+		intel_cleanup_ring_buffer(ring);
 }
 
 int
@@ -3592,7 +3597,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret, i;
+	int ret;
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		return 0;
@@ -3614,10 +3619,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	BUG_ON(!list_empty(&dev_priv->mm.active_list));
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		BUG_ON(!list_empty(&dev_priv->ring[i].active_list));
-		BUG_ON(!list_empty(&dev_priv->ring[i].request_list));
-	}
 	mutex_unlock(&dev->struct_mutex);
 
 	ret = drm_irq_install(dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 3bcf045..ae7c24e 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -168,7 +168,7 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj, *next;
 	bool lists_empty;
-	int ret,i;
+	int ret;
 
 	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
 		       list_empty(&dev_priv->mm.flushing_list) &&
@@ -178,17 +178,13 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 
 	trace_i915_gem_evict_everything(dev, purgeable_only);
 
-	ret = i915_gpu_idle(dev);
-	if (ret)
-		return ret;
-
 	/* The gpu_idle will flush everything in the write domain to the
 	 * active list. Then we must move everything off the active list
 	 * with retire requests.
 	 */
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		if (WARN_ON(!list_empty(&dev_priv->ring[i].gpu_write_list)))
-			return -EBUSY;
+	ret = i915_gpu_idle(dev);
+	if (ret)
+		return ret;
 
 	i915_gem_retire_requests(dev);
 
@@ -203,5 +199,5 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 		}
 	}
 
-	return ret;
+	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2a062d7..cc4a633 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1022,15 +1022,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
 				  struct drm_i915_error_state *error)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	struct drm_i915_gem_request *request;
 	int i, count;
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		struct intel_ring_buffer *ring = &dev_priv->ring[i];
-
-		if (ring->obj == NULL)
-			continue;
-
+	for_each_ring(ring, dev_priv, i) {
 		i915_record_ring_state(dev, error, ring);
 
 		error->ring[i].batchbuffer =
@@ -1295,6 +1291,8 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 void i915_handle_error(struct drm_device *dev, bool wedged)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	int i;
 
 	i915_capture_error_state(dev);
 	i915_report_and_clear_eir(dev);
@@ -1306,11 +1304,8 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
 		/*
 		 * Wakeup waiting processes so they don't hang
 		 */
-		wake_up_all(&dev_priv->ring[RCS].irq_queue);
-		if (HAS_BSD(dev))
-			wake_up_all(&dev_priv->ring[VCS].irq_queue);
-		if (HAS_BLT(dev))
-			wake_up_all(&dev_priv->ring[BCS].irq_queue);
+		for_each_ring(ring, dev_priv, i)
+			wake_up_all(&ring->irq_queue);
 	}
 
 	queue_work(dev_priv->wq, &dev_priv->error_work);
@@ -1515,11 +1510,6 @@ ring_last_seqno(struct intel_ring_buffer *ring)
 
 static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
 {
-	/* We don't check whether the ring even exists before calling this
-	 * function. Hence check whether it's initialized. */
-	if (ring->obj == NULL)
-		return true;
-
 	if (list_empty(&ring->request_list) ||
 	    i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
 		/* Issue a wake-up to catch stuck h/w. */
@@ -1553,26 +1543,25 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
 	if (dev_priv->hangcheck_count++ > 1) {
+		bool hung = true;
+
 		DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
 		i915_handle_error(dev, true);
 
 		if (!IS_GEN2(dev)) {
+			struct intel_ring_buffer *ring;
+			int i;
+
 			/* Is the chip hanging on a WAIT_FOR_EVENT?
 			 * If so we can simply poke the RB_WAIT bit
 			 * and break the hang. This should work on
 			 * all but the second generation chipsets.
 			 */
-			if (kick_ring(&dev_priv->ring[RCS]))
-				return false;
-
-			if (HAS_BSD(dev) && kick_ring(&dev_priv->ring[VCS]))
-				return false;
-
-			if (HAS_BLT(dev) && kick_ring(&dev_priv->ring[BCS]))
-				return false;
+			for_each_ring(ring, dev_priv, i)
+				hung &= !kick_ring(ring);
 		}
 
-		return true;
+		return hung;
 	}
 
 	return false;
@@ -1588,16 +1577,23 @@ void i915_hangcheck_elapsed(unsigned long data)
 {
 	struct drm_device *dev = (struct drm_device *)data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
-	bool err = false;
+	uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
+	struct intel_ring_buffer *ring;
+	bool err = false, idle;
+	int i;
 
 	if (!i915_enable_hangcheck)
 		return;
 
+	memset(acthd, 0, sizeof(acthd));
+	idle = true;
+	for_each_ring(ring, dev_priv, i) {
+	    idle &= i915_hangcheck_ring_idle(ring, &err);
+	    acthd[i] = intel_ring_get_active_head(ring);
+	}
+
 	/* If all work is done then ACTHD clearly hasn't advanced. */
-	if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
-	    i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
-	    i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
+	if (idle) {
 		if (err) {
 			if (i915_hangcheck_hung(dev))
 				return;
@@ -1616,15 +1612,8 @@ void i915_hangcheck_elapsed(unsigned long data)
 		instdone = I915_READ(INSTDONE_I965);
 		instdone1 = I915_READ(INSTDONE1);
 	}
-	acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
-	acthd_bsd = HAS_BSD(dev) ?
-		intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
-	acthd_blt = HAS_BLT(dev) ?
-		intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
 
-	if (dev_priv->last_acthd == acthd &&
-	    dev_priv->last_acthd_bsd == acthd_bsd &&
-	    dev_priv->last_acthd_blt == acthd_blt &&
+	if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
 	    dev_priv->last_instdone == instdone &&
 	    dev_priv->last_instdone1 == instdone1) {
 		if (i915_hangcheck_hung(dev))
@@ -1632,9 +1621,7 @@ void i915_hangcheck_elapsed(unsigned long data)
 	} else {
 		dev_priv->hangcheck_count = 0;
 
-		dev_priv->last_acthd = acthd;
-		dev_priv->last_acthd_bsd = acthd_bsd;
-		dev_priv->last_acthd_blt = acthd_blt;
+		memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
 		dev_priv->last_instdone = instdone;
 		dev_priv->last_instdone1 = instdone1;
 	}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 8f8d1da..8e79ff6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2326,6 +2326,7 @@ int intel_enable_rc6(const struct drm_device *dev)
 
 void gen6_enable_rps(struct drm_i915_private *dev_priv)
 {
+	struct intel_ring_buffer *ring;
 	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
 	u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 	u32 pcu_mbox, rc6_mask = 0;
@@ -2360,8 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
+	for_each_ring(ring, dev_priv, i)
+		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
 
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index baba757..55d3da2 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -119,6 +119,12 @@ struct  intel_ring_buffer {
 	void *private;
 };
 
+static inline bool
+intel_ring_initialized(struct intel_ring_buffer *ring)
+{
+	return ring->obj != NULL;
+}
+
 static inline unsigned
 intel_ring_flag(struct intel_ring_buffer *ring)
 {
-- 
1.7.10

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

* [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch
  2012-05-11 13:29 [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Chris Wilson
@ 2012-05-11 13:29 ` Chris Wilson
  2012-05-11 19:53   ` Ben Widawsky
  2012-05-11 13:29 ` [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks Chris Wilson
  2012-05-11 19:46 ` [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Ben Widawsky
  2 siblings, 1 reply; 8+ messages in thread
From: Chris Wilson @ 2012-05-11 13:29 UTC (permalink / raw)
  To: intel-gfx

Rather than use the magic feature tests HAS_BLT/HAS_BSD just check
whether the ring we are about to dispatch the execbuffer on is
initialised.

v2: Use intel_ring_initialized()

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 21fc11d..974a9f1 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1064,17 +1064,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		ring = &dev_priv->ring[RCS];
 		break;
 	case I915_EXEC_BSD:
-		if (!HAS_BSD(dev)) {
-			DRM_DEBUG("execbuf with invalid ring (BSD)\n");
-			return -EINVAL;
-		}
 		ring = &dev_priv->ring[VCS];
 		break;
 	case I915_EXEC_BLT:
-		if (!HAS_BLT(dev)) {
-			DRM_DEBUG("execbuf with invalid ring (BLT)\n");
-			return -EINVAL;
-		}
 		ring = &dev_priv->ring[BCS];
 		break;
 	default:
@@ -1082,6 +1074,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			  (int)(args->flags & I915_EXEC_RING_MASK));
 		return -EINVAL;
 	}
+	if (!intel_ring_initialized(ring)) {
+		DRM_DEBUG("execbuf with invalid ring: %d\n",
+			  (int)(args->flags & I915_EXEC_RING_MASK));
+		return -EINVAL;
+	}
 
 	mode = args->flags & I915_EXEC_CONSTANTS_MASK;
 	mask = I915_EXEC_CONSTANTS_MASK;
-- 
1.7.10

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

* [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks
  2012-05-11 13:29 [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Chris Wilson
  2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
@ 2012-05-11 13:29 ` Chris Wilson
  2012-05-11 19:58   ` Ben Widawsky
  2012-05-11 19:46 ` [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Ben Widawsky
  2 siblings, 1 reply; 8+ messages in thread
From: Chris Wilson @ 2012-05-11 13:29 UTC (permalink / raw)
  To: intel-gfx

When userspace asks whether the driver supports the BLT or BSD rings for
this chip, simply report whether those particular rings are initialised

v2: Use intel_ring_initialized()

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_dma.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 006ea47..b0df294 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -980,10 +980,10 @@ static int i915_getparam(struct drm_device *dev, void *data,
 		value = 1;
 		break;
 	case I915_PARAM_HAS_BSD:
-		value = HAS_BSD(dev);
+		value = intel_ring_initialized(&dev_priv->ring[VCS]);
 		break;
 	case I915_PARAM_HAS_BLT:
-		value = HAS_BLT(dev);
+		value = intel_ring_initialized(&dev_priv->ring[BCS]);
 		break;
 	case I915_PARAM_HAS_RELAXED_FENCING:
 		value = 1;
-- 
1.7.10

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

* Re: [PATCH 1/3] drm/i915: Introduce for_each_ring() macro
  2012-05-11 13:29 [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Chris Wilson
  2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
  2012-05-11 13:29 ` [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks Chris Wilson
@ 2012-05-11 19:46 ` Ben Widawsky
  2012-05-13 13:35   ` Daniel Vetter
  2 siblings, 1 reply; 8+ messages in thread
From: Ben Widawsky @ 2012-05-11 19:46 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Fri, 11 May 2012 14:29:30 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> In many places we wish to iterate over the rings associated with the
> GPU, so refactor them to use a common macro.
> 
> Along the way, there are a few code removals that should be side-effect
> free and some rearrangement which should only have a cosmetic impact,
> such as error-state.
> 
> v2: Pull in a couple of suggestions from Ben and Daniel for
> intel_ring_initialized() and not removing the warning (just moving them
> to a new home, closer to the error).

I would have liked the commit message update explaining the new behavior
of hangcheck_elapsed, and hangcheck_ring_idle just in case this ends up
the result of a bisection. I can live without it though.

> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c     |    9 ++--
>  drivers/gpu/drm/i915/i915_drv.c         |   10 ++---
>  drivers/gpu/drm/i915/i915_drv.h         |    9 ++--
>  drivers/gpu/drm/i915/i915_gem.c         |   39 ++++++++---------
>  drivers/gpu/drm/i915/i915_gem_evict.c   |   14 +++----
>  drivers/gpu/drm/i915/i915_irq.c         |   69 +++++++++++++------------------
>  drivers/gpu/drm/i915/intel_pm.c         |    5 ++-
>  drivers/gpu/drm/i915/intel_ringbuffer.h |    6 +++
>  8 files changed, 76 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 950f72a..eb2b3c2 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -699,6 +699,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
>  	struct drm_device *dev = error_priv->dev;
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	struct drm_i915_error_state *error = error_priv->error;
> +	struct intel_ring_buffer *ring;
>  	int i, j, page, offset, elt;
>  
>  	if (!error) {
> @@ -706,7 +707,6 @@ static int i915_error_state(struct seq_file *m, void *unused)
>  		return 0;
>  	}
>  
> -
>  	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
>  		   error->time.tv_usec);
>  	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
> @@ -722,11 +722,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
>  		seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
>  	}
>  
> -	i915_ring_error_state(m, dev, error, RCS);
> -	if (HAS_BLT(dev))
> -		i915_ring_error_state(m, dev, error, BCS);
> -	if (HAS_BSD(dev))
> -		i915_ring_error_state(m, dev, error, VCS);
> +	for_each_ring(ring, dev_priv, i)
> +		i915_ring_error_state(m, dev, error, i);
>  
>  	if (error->active_bo)
>  		print_error_buffers(m, "Active",
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 5898be9..3947804 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -893,15 +893,15 @@ int i915_reset(struct drm_device *dev)
>  	 */
>  	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
>  			!dev_priv->mm.suspended) {
> +		struct intel_ring_buffer *ring;
> +		int i;
> +
>  		dev_priv->mm.suspended = 0;
>  
>  		i915_gem_init_swizzling(dev);
>  
> -		dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
> -		if (HAS_BSD(dev))
> -		    dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
> -		if (HAS_BLT(dev))
> -		    dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
> +		for_each_ring(ring, dev_priv, i)
> +			ring->init(ring);
>  
>  		i915_gem_init_ppgtt(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 83a557c..11c7a6a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -410,9 +410,7 @@ typedef struct drm_i915_private {
>  #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
>  	struct timer_list hangcheck_timer;
>  	int hangcheck_count;
> -	uint32_t last_acthd;
> -	uint32_t last_acthd_bsd;
> -	uint32_t last_acthd_blt;
> +	uint32_t last_acthd[I915_NUM_RINGS];
>  	uint32_t last_instdone;
>  	uint32_t last_instdone1;
>  
> @@ -820,6 +818,11 @@ typedef struct drm_i915_private {
>  	struct drm_property *force_audio_property;
>  } drm_i915_private_t;
>  
> +/* Iterate over initialised rings */
> +#define for_each_ring(ring__, dev_priv__, i__) \
> +	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> +		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> +
>  enum hdmi_force_audio {
>  	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
>  	HDMI_AUDIO_OFF,			/* force turn off HDMI audio */
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 44a5f24..6d2180c 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -1655,10 +1655,11 @@ void i915_gem_reset(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_i915_gem_object *obj;
> +	struct intel_ring_buffer *ring;
>  	int i;
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++)
> -		i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]);
> +	for_each_ring(ring, dev_priv, i)
> +		i915_gem_reset_ring_lists(dev_priv, ring);
>  
>  	/* Remove anything from the flushing lists. The GPU cache is likely
>  	 * to be lost on reset along with the data, so simply move the
> @@ -1763,10 +1764,11 @@ void
>  i915_gem_retire_requests(struct drm_device *dev)
>  {
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> +	struct intel_ring_buffer *ring;
>  	int i;
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++)
> -		i915_gem_retire_requests_ring(&dev_priv->ring[i]);
> +	for_each_ring(ring, dev_priv, i)
> +		i915_gem_retire_requests_ring(ring);
>  }
>  
>  static void
> @@ -1774,6 +1776,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
>  {
>  	drm_i915_private_t *dev_priv;
>  	struct drm_device *dev;
> +	struct intel_ring_buffer *ring;
>  	bool idle;
>  	int i;
>  
> @@ -1793,9 +1796,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
>  	 * objects indefinitely.
>  	 */
>  	idle = true;
> -	for (i = 0; i < I915_NUM_RINGS; i++) {
> -		struct intel_ring_buffer *ring = &dev_priv->ring[i];
> -
> +	for_each_ring(ring, dev_priv, i) {
>  		if (!list_empty(&ring->gpu_write_list)) {
>  			struct drm_i915_gem_request *request;
>  			int ret;
> @@ -2137,13 +2138,18 @@ static int i915_ring_idle(struct intel_ring_buffer *ring)
>  int i915_gpu_idle(struct drm_device *dev)
>  {
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> +	struct intel_ring_buffer *ring;
>  	int ret, i;
>  
>  	/* Flush everything onto the inactive list. */
> -	for (i = 0; i < I915_NUM_RINGS; i++) {
> -		ret = i915_ring_idle(&dev_priv->ring[i]);
> +	for_each_ring(ring, dev_priv, i) {
> +		ret = i915_ring_idle(ring);
>  		if (ret)
>  			return ret;
> +
> +		/* Is the device fubar? */
> +		if (WARN_ON(!list_empty(&ring->gpu_write_list)))
> +			return -EBUSY;
>  	}
>  
>  	return 0;
> @@ -3463,9 +3469,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
>  		/* GFX_MODE is per-ring on gen7+ */
>  	}
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++) {
> -		ring = &dev_priv->ring[i];
> -
> +	for_each_ring(ring, dev_priv, i) {
>  		if (INTEL_INFO(dev)->gen >= 7)
>  			I915_WRITE(RING_MODE_GEN7(ring),
>  				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
> @@ -3581,10 +3585,11 @@ void
>  i915_gem_cleanup_ringbuffer(struct drm_device *dev)
>  {
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> +	struct intel_ring_buffer *ring;
>  	int i;
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++)
> -		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
> +	for_each_ring(ring, dev_priv, i)
> +		intel_cleanup_ring_buffer(ring);
>  }
>  
>  int
> @@ -3592,7 +3597,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
>  		       struct drm_file *file_priv)
>  {
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> -	int ret, i;
> +	int ret;
>  
>  	if (drm_core_check_feature(dev, DRIVER_MODESET))
>  		return 0;
> @@ -3614,10 +3619,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
>  	BUG_ON(!list_empty(&dev_priv->mm.active_list));
>  	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
>  	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
> -	for (i = 0; i < I915_NUM_RINGS; i++) {
> -		BUG_ON(!list_empty(&dev_priv->ring[i].active_list));
> -		BUG_ON(!list_empty(&dev_priv->ring[i].request_list));
> -	}
>  	mutex_unlock(&dev->struct_mutex);
>  
>  	ret = drm_irq_install(dev);
> diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> index 3bcf045..ae7c24e 100644
> --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> @@ -168,7 +168,7 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	struct drm_i915_gem_object *obj, *next;
>  	bool lists_empty;
> -	int ret,i;
> +	int ret;
>  
>  	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
>  		       list_empty(&dev_priv->mm.flushing_list) &&
> @@ -178,17 +178,13 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
>  
>  	trace_i915_gem_evict_everything(dev, purgeable_only);
>  
> -	ret = i915_gpu_idle(dev);
> -	if (ret)
> -		return ret;
> -
>  	/* The gpu_idle will flush everything in the write domain to the
>  	 * active list. Then we must move everything off the active list
>  	 * with retire requests.
>  	 */
> -	for (i = 0; i < I915_NUM_RINGS; i++)
> -		if (WARN_ON(!list_empty(&dev_priv->ring[i].gpu_write_list)))
> -			return -EBUSY;
> +	ret = i915_gpu_idle(dev);
> +	if (ret)
> +		return ret;
>  
>  	i915_gem_retire_requests(dev);
>  
> @@ -203,5 +199,5 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
>  		}
>  	}
>  
> -	return ret;
> +	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 2a062d7..cc4a633 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1022,15 +1022,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
>  				  struct drm_i915_error_state *error)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_ring_buffer *ring;
>  	struct drm_i915_gem_request *request;
>  	int i, count;
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++) {
> -		struct intel_ring_buffer *ring = &dev_priv->ring[i];
> -
> -		if (ring->obj == NULL)
> -			continue;
> -
> +	for_each_ring(ring, dev_priv, i) {
>  		i915_record_ring_state(dev, error, ring);
>  
>  		error->ring[i].batchbuffer =
> @@ -1295,6 +1291,8 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
>  void i915_handle_error(struct drm_device *dev, bool wedged)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_ring_buffer *ring;
> +	int i;
>  
>  	i915_capture_error_state(dev);
>  	i915_report_and_clear_eir(dev);
> @@ -1306,11 +1304,8 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
>  		/*
>  		 * Wakeup waiting processes so they don't hang
>  		 */
> -		wake_up_all(&dev_priv->ring[RCS].irq_queue);
> -		if (HAS_BSD(dev))
> -			wake_up_all(&dev_priv->ring[VCS].irq_queue);
> -		if (HAS_BLT(dev))
> -			wake_up_all(&dev_priv->ring[BCS].irq_queue);
> +		for_each_ring(ring, dev_priv, i)
> +			wake_up_all(&ring->irq_queue);
>  	}
>  
>  	queue_work(dev_priv->wq, &dev_priv->error_work);
> @@ -1515,11 +1510,6 @@ ring_last_seqno(struct intel_ring_buffer *ring)
>  
>  static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
>  {
> -	/* We don't check whether the ring even exists before calling this
> -	 * function. Hence check whether it's initialized. */
> -	if (ring->obj == NULL)
> -		return true;
> -
>  	if (list_empty(&ring->request_list) ||
>  	    i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
>  		/* Issue a wake-up to catch stuck h/w. */
> @@ -1553,26 +1543,25 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  
>  	if (dev_priv->hangcheck_count++ > 1) {
> +		bool hung = true;
> +
>  		DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
>  		i915_handle_error(dev, true);
>  
>  		if (!IS_GEN2(dev)) {
> +			struct intel_ring_buffer *ring;
> +			int i;
> +
>  			/* Is the chip hanging on a WAIT_FOR_EVENT?
>  			 * If so we can simply poke the RB_WAIT bit
>  			 * and break the hang. This should work on
>  			 * all but the second generation chipsets.
>  			 */
> -			if (kick_ring(&dev_priv->ring[RCS]))
> -				return false;
> -
> -			if (HAS_BSD(dev) && kick_ring(&dev_priv->ring[VCS]))
> -				return false;
> -
> -			if (HAS_BLT(dev) && kick_ring(&dev_priv->ring[BCS]))
> -				return false;
> +			for_each_ring(ring, dev_priv, i)
> +				hung &= !kick_ring(ring);
>  		}
>  
> -		return true;
> +		return hung;
>  	}
>  
>  	return false;
> @@ -1588,16 +1577,23 @@ void i915_hangcheck_elapsed(unsigned long data)
>  {
>  	struct drm_device *dev = (struct drm_device *)data;
>  	drm_i915_private_t *dev_priv = dev->dev_private;
> -	uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
> -	bool err = false;
> +	uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
> +	struct intel_ring_buffer *ring;
> +	bool err = false, idle;
> +	int i;
>  
>  	if (!i915_enable_hangcheck)
>  		return;
>  
> +	memset(acthd, 0, sizeof(acthd));
> +	idle = true;
> +	for_each_ring(ring, dev_priv, i) {
> +	    idle &= i915_hangcheck_ring_idle(ring, &err);
> +	    acthd[i] = intel_ring_get_active_head(ring);
> +	}
> +
>  	/* If all work is done then ACTHD clearly hasn't advanced. */
> -	if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
> -	    i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
> -	    i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
> +	if (idle) {
>  		if (err) {
>  			if (i915_hangcheck_hung(dev))
>  				return;
> @@ -1616,15 +1612,8 @@ void i915_hangcheck_elapsed(unsigned long data)
>  		instdone = I915_READ(INSTDONE_I965);
>  		instdone1 = I915_READ(INSTDONE1);
>  	}
> -	acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
> -	acthd_bsd = HAS_BSD(dev) ?
> -		intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
> -	acthd_blt = HAS_BLT(dev) ?
> -		intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
>  
> -	if (dev_priv->last_acthd == acthd &&
> -	    dev_priv->last_acthd_bsd == acthd_bsd &&
> -	    dev_priv->last_acthd_blt == acthd_blt &&
> +	if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
>  	    dev_priv->last_instdone == instdone &&
>  	    dev_priv->last_instdone1 == instdone1) {
>  		if (i915_hangcheck_hung(dev))
> @@ -1632,9 +1621,7 @@ void i915_hangcheck_elapsed(unsigned long data)
>  	} else {
>  		dev_priv->hangcheck_count = 0;
>  
> -		dev_priv->last_acthd = acthd;
> -		dev_priv->last_acthd_bsd = acthd_bsd;
> -		dev_priv->last_acthd_blt = acthd_blt;
> +		memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
>  		dev_priv->last_instdone = instdone;
>  		dev_priv->last_instdone1 = instdone1;
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 8f8d1da..8e79ff6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2326,6 +2326,7 @@ int intel_enable_rc6(const struct drm_device *dev)
>  
>  void gen6_enable_rps(struct drm_i915_private *dev_priv)
>  {
> +	struct intel_ring_buffer *ring;
>  	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
>  	u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
>  	u32 pcu_mbox, rc6_mask = 0;
> @@ -2360,8 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
>  	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
>  	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
>  
> -	for (i = 0; i < I915_NUM_RINGS; i++)
> -		I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
> +	for_each_ring(ring, dev_priv, i)
> +		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
>  
>  	I915_WRITE(GEN6_RC_SLEEP, 0);
>  	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index baba757..55d3da2 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -119,6 +119,12 @@ struct  intel_ring_buffer {
>  	void *private;
>  };
>  
> +static inline bool
> +intel_ring_initialized(struct intel_ring_buffer *ring)
> +{
> +	return ring->obj != NULL;
> +}
> +
>  static inline unsigned
>  intel_ring_flag(struct intel_ring_buffer *ring)
>  {



-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch
  2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
@ 2012-05-11 19:53   ` Ben Widawsky
  0 siblings, 0 replies; 8+ messages in thread
From: Ben Widawsky @ 2012-05-11 19:53 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Fri, 11 May 2012 14:29:31 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> Rather than use the magic feature tests HAS_BLT/HAS_BSD just check
> whether the ring we are about to dispatch the execbuffer on is
> initialised.
> 
> v2: Use intel_ring_initialized()
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
> ---
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c |   13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 21fc11d..974a9f1 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -1064,17 +1064,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  		ring = &dev_priv->ring[RCS];
>  		break;
>  	case I915_EXEC_BSD:
> -		if (!HAS_BSD(dev)) {
> -			DRM_DEBUG("execbuf with invalid ring (BSD)\n");
> -			return -EINVAL;
> -		}
>  		ring = &dev_priv->ring[VCS];
>  		break;
>  	case I915_EXEC_BLT:
> -		if (!HAS_BLT(dev)) {
> -			DRM_DEBUG("execbuf with invalid ring (BLT)\n");
> -			return -EINVAL;
> -		}
>  		ring = &dev_priv->ring[BCS];
>  		break;
>  	default:
> @@ -1082,6 +1074,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
>  			  (int)(args->flags & I915_EXEC_RING_MASK));
>  		return -EINVAL;
>  	}
> +	if (!intel_ring_initialized(ring)) {
> +		DRM_DEBUG("execbuf with invalid ring: %d\n",
> +			  (int)(args->flags & I915_EXEC_RING_MASK));
> +		return -EINVAL;
> +	}
>  
>  	mode = args->flags & I915_EXEC_CONSTANTS_MASK;
>  	mask = I915_EXEC_CONSTANTS_MASK;



-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks
  2012-05-11 13:29 ` [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks Chris Wilson
@ 2012-05-11 19:58   ` Ben Widawsky
  2012-05-11 20:24     ` Chris Wilson
  0 siblings, 1 reply; 8+ messages in thread
From: Ben Widawsky @ 2012-05-11 19:58 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On Fri, 11 May 2012 14:29:32 +0100
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> When userspace asks whether the driver supports the BLT or BSD rings for
> this chip, simply report whether those particular rings are initialised
> 

This was the one place where I felt HAS_BLT and HAS_BSD was sort of
nice to keep around to distinguish HW has the ring vs. HW successfully
initialized the rings.

> v2: Use intel_ring_initialized()
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_dma.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 006ea47..b0df294 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -980,10 +980,10 @@ static int i915_getparam(struct drm_device *dev, void *data,
>  		value = 1;
>  		break;
>  	case I915_PARAM_HAS_BSD:
> -		value = HAS_BSD(dev);
> +		value = intel_ring_initialized(&dev_priv->ring[VCS]);
>  		break;
>  	case I915_PARAM_HAS_BLT:
> -		value = HAS_BLT(dev);
> +		value = intel_ring_initialized(&dev_priv->ring[BCS]);
>  		break;
>  	case I915_PARAM_HAS_RELAXED_FENCING:
>  		value = 1;



-- 
Ben Widawsky, Intel Open Source Technology Center

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

* Re: [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks
  2012-05-11 19:58   ` Ben Widawsky
@ 2012-05-11 20:24     ` Chris Wilson
  0 siblings, 0 replies; 8+ messages in thread
From: Chris Wilson @ 2012-05-11 20:24 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx

On Fri, 11 May 2012 12:58:14 -0700, Ben Widawsky <ben@bwidawsk.net> wrote:
> On Fri, 11 May 2012 14:29:32 +0100
> Chris Wilson <chris@chris-wilson.co.uk> wrote:
> 
> > When userspace asks whether the driver supports the BLT or BSD rings for
> > this chip, simply report whether those particular rings are initialised
> > 
> 
> This was the one place where I felt HAS_BLT and HAS_BSD was sort of
> nice to keep around to distinguish HW has the ring vs. HW successfully
> initialized the rings.

The hw supporting those rings is useless if the driver doesn't, imo.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 1/3] drm/i915: Introduce for_each_ring() macro
  2012-05-11 19:46 ` [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Ben Widawsky
@ 2012-05-13 13:35   ` Daniel Vetter
  0 siblings, 0 replies; 8+ messages in thread
From: Daniel Vetter @ 2012-05-13 13:35 UTC (permalink / raw)
  To: Ben Widawsky; +Cc: intel-gfx

On Fri, May 11, 2012 at 12:46:23PM -0700, Ben Widawsky wrote:
> On Fri, 11 May 2012 14:29:30 +0100
> Chris Wilson <chris@chris-wilson.co.uk> wrote:
> 
> > In many places we wish to iterate over the rings associated with the
> > GPU, so refactor them to use a common macro.
> > 
> > Along the way, there are a few code removals that should be side-effect
> > free and some rearrangement which should only have a cosmetic impact,
> > such as error-state.
> > 
> > v2: Pull in a couple of suggestions from Ben and Daniel for
> > intel_ring_initialized() and not removing the warning (just moving them
> > to a new home, closer to the error).
> 
> I would have liked the commit message update explaining the new behavior
> of hangcheck_elapsed, and hangcheck_ring_idle just in case this ends up
> the result of a bisection. I can live without it though.
> 
> > 
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
I've queued all 3 patches for -next (with a small note added to patch 1 as
suggested by Ben), thanks for the patch.
-Daniel
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c     |    9 ++--
> >  drivers/gpu/drm/i915/i915_drv.c         |   10 ++---
> >  drivers/gpu/drm/i915/i915_drv.h         |    9 ++--
> >  drivers/gpu/drm/i915/i915_gem.c         |   39 ++++++++---------
> >  drivers/gpu/drm/i915/i915_gem_evict.c   |   14 +++----
> >  drivers/gpu/drm/i915/i915_irq.c         |   69 +++++++++++++------------------
> >  drivers/gpu/drm/i915/intel_pm.c         |    5 ++-
> >  drivers/gpu/drm/i915/intel_ringbuffer.h |    6 +++
> >  8 files changed, 76 insertions(+), 85 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 950f72a..eb2b3c2 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -699,6 +699,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
> >  	struct drm_device *dev = error_priv->dev;
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> >  	struct drm_i915_error_state *error = error_priv->error;
> > +	struct intel_ring_buffer *ring;
> >  	int i, j, page, offset, elt;
> >  
> >  	if (!error) {
> > @@ -706,7 +707,6 @@ static int i915_error_state(struct seq_file *m, void *unused)
> >  		return 0;
> >  	}
> >  
> > -
> >  	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
> >  		   error->time.tv_usec);
> >  	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
> > @@ -722,11 +722,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
> >  		seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
> >  	}
> >  
> > -	i915_ring_error_state(m, dev, error, RCS);
> > -	if (HAS_BLT(dev))
> > -		i915_ring_error_state(m, dev, error, BCS);
> > -	if (HAS_BSD(dev))
> > -		i915_ring_error_state(m, dev, error, VCS);
> > +	for_each_ring(ring, dev_priv, i)
> > +		i915_ring_error_state(m, dev, error, i);
> >  
> >  	if (error->active_bo)
> >  		print_error_buffers(m, "Active",
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 5898be9..3947804 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -893,15 +893,15 @@ int i915_reset(struct drm_device *dev)
> >  	 */
> >  	if (drm_core_check_feature(dev, DRIVER_MODESET) ||
> >  			!dev_priv->mm.suspended) {
> > +		struct intel_ring_buffer *ring;
> > +		int i;
> > +
> >  		dev_priv->mm.suspended = 0;
> >  
> >  		i915_gem_init_swizzling(dev);
> >  
> > -		dev_priv->ring[RCS].init(&dev_priv->ring[RCS]);
> > -		if (HAS_BSD(dev))
> > -		    dev_priv->ring[VCS].init(&dev_priv->ring[VCS]);
> > -		if (HAS_BLT(dev))
> > -		    dev_priv->ring[BCS].init(&dev_priv->ring[BCS]);
> > +		for_each_ring(ring, dev_priv, i)
> > +			ring->init(ring);
> >  
> >  		i915_gem_init_ppgtt(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 83a557c..11c7a6a 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -410,9 +410,7 @@ typedef struct drm_i915_private {
> >  #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
> >  	struct timer_list hangcheck_timer;
> >  	int hangcheck_count;
> > -	uint32_t last_acthd;
> > -	uint32_t last_acthd_bsd;
> > -	uint32_t last_acthd_blt;
> > +	uint32_t last_acthd[I915_NUM_RINGS];
> >  	uint32_t last_instdone;
> >  	uint32_t last_instdone1;
> >  
> > @@ -820,6 +818,11 @@ typedef struct drm_i915_private {
> >  	struct drm_property *force_audio_property;
> >  } drm_i915_private_t;
> >  
> > +/* Iterate over initialised rings */
> > +#define for_each_ring(ring__, dev_priv__, i__) \
> > +	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
> > +		if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
> > +
> >  enum hdmi_force_audio {
> >  	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
> >  	HDMI_AUDIO_OFF,			/* force turn off HDMI audio */
> > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> > index 44a5f24..6d2180c 100644
> > --- a/drivers/gpu/drm/i915/i915_gem.c
> > +++ b/drivers/gpu/drm/i915/i915_gem.c
> > @@ -1655,10 +1655,11 @@ void i915_gem_reset(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct drm_i915_gem_object *obj;
> > +	struct intel_ring_buffer *ring;
> >  	int i;
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++)
> > -		i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]);
> > +	for_each_ring(ring, dev_priv, i)
> > +		i915_gem_reset_ring_lists(dev_priv, ring);
> >  
> >  	/* Remove anything from the flushing lists. The GPU cache is likely
> >  	 * to be lost on reset along with the data, so simply move the
> > @@ -1763,10 +1764,11 @@ void
> >  i915_gem_retire_requests(struct drm_device *dev)
> >  {
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > +	struct intel_ring_buffer *ring;
> >  	int i;
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++)
> > -		i915_gem_retire_requests_ring(&dev_priv->ring[i]);
> > +	for_each_ring(ring, dev_priv, i)
> > +		i915_gem_retire_requests_ring(ring);
> >  }
> >  
> >  static void
> > @@ -1774,6 +1776,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
> >  {
> >  	drm_i915_private_t *dev_priv;
> >  	struct drm_device *dev;
> > +	struct intel_ring_buffer *ring;
> >  	bool idle;
> >  	int i;
> >  
> > @@ -1793,9 +1796,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
> >  	 * objects indefinitely.
> >  	 */
> >  	idle = true;
> > -	for (i = 0; i < I915_NUM_RINGS; i++) {
> > -		struct intel_ring_buffer *ring = &dev_priv->ring[i];
> > -
> > +	for_each_ring(ring, dev_priv, i) {
> >  		if (!list_empty(&ring->gpu_write_list)) {
> >  			struct drm_i915_gem_request *request;
> >  			int ret;
> > @@ -2137,13 +2138,18 @@ static int i915_ring_idle(struct intel_ring_buffer *ring)
> >  int i915_gpu_idle(struct drm_device *dev)
> >  {
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > +	struct intel_ring_buffer *ring;
> >  	int ret, i;
> >  
> >  	/* Flush everything onto the inactive list. */
> > -	for (i = 0; i < I915_NUM_RINGS; i++) {
> > -		ret = i915_ring_idle(&dev_priv->ring[i]);
> > +	for_each_ring(ring, dev_priv, i) {
> > +		ret = i915_ring_idle(ring);
> >  		if (ret)
> >  			return ret;
> > +
> > +		/* Is the device fubar? */
> > +		if (WARN_ON(!list_empty(&ring->gpu_write_list)))
> > +			return -EBUSY;
> >  	}
> >  
> >  	return 0;
> > @@ -3463,9 +3469,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)
> >  		/* GFX_MODE is per-ring on gen7+ */
> >  	}
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++) {
> > -		ring = &dev_priv->ring[i];
> > -
> > +	for_each_ring(ring, dev_priv, i) {
> >  		if (INTEL_INFO(dev)->gen >= 7)
> >  			I915_WRITE(RING_MODE_GEN7(ring),
> >  				   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
> > @@ -3581,10 +3585,11 @@ void
> >  i915_gem_cleanup_ringbuffer(struct drm_device *dev)
> >  {
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > +	struct intel_ring_buffer *ring;
> >  	int i;
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++)
> > -		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
> > +	for_each_ring(ring, dev_priv, i)
> > +		intel_cleanup_ring_buffer(ring);
> >  }
> >  
> >  int
> > @@ -3592,7 +3597,7 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
> >  		       struct drm_file *file_priv)
> >  {
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > -	int ret, i;
> > +	int ret;
> >  
> >  	if (drm_core_check_feature(dev, DRIVER_MODESET))
> >  		return 0;
> > @@ -3614,10 +3619,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
> >  	BUG_ON(!list_empty(&dev_priv->mm.active_list));
> >  	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
> >  	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
> > -	for (i = 0; i < I915_NUM_RINGS; i++) {
> > -		BUG_ON(!list_empty(&dev_priv->ring[i].active_list));
> > -		BUG_ON(!list_empty(&dev_priv->ring[i].request_list));
> > -	}
> >  	mutex_unlock(&dev->struct_mutex);
> >  
> >  	ret = drm_irq_install(dev);
> > diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
> > index 3bcf045..ae7c24e 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_evict.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_evict.c
> > @@ -168,7 +168,7 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> >  	struct drm_i915_gem_object *obj, *next;
> >  	bool lists_empty;
> > -	int ret,i;
> > +	int ret;
> >  
> >  	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
> >  		       list_empty(&dev_priv->mm.flushing_list) &&
> > @@ -178,17 +178,13 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
> >  
> >  	trace_i915_gem_evict_everything(dev, purgeable_only);
> >  
> > -	ret = i915_gpu_idle(dev);
> > -	if (ret)
> > -		return ret;
> > -
> >  	/* The gpu_idle will flush everything in the write domain to the
> >  	 * active list. Then we must move everything off the active list
> >  	 * with retire requests.
> >  	 */
> > -	for (i = 0; i < I915_NUM_RINGS; i++)
> > -		if (WARN_ON(!list_empty(&dev_priv->ring[i].gpu_write_list)))
> > -			return -EBUSY;
> > +	ret = i915_gpu_idle(dev);
> > +	if (ret)
> > +		return ret;
> >  
> >  	i915_gem_retire_requests(dev);
> >  
> > @@ -203,5 +199,5 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
> >  		}
> >  	}
> >  
> > -	return ret;
> > +	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 2a062d7..cc4a633 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -1022,15 +1022,11 @@ static void i915_gem_record_rings(struct drm_device *dev,
> >  				  struct drm_i915_error_state *error)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	struct intel_ring_buffer *ring;
> >  	struct drm_i915_gem_request *request;
> >  	int i, count;
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++) {
> > -		struct intel_ring_buffer *ring = &dev_priv->ring[i];
> > -
> > -		if (ring->obj == NULL)
> > -			continue;
> > -
> > +	for_each_ring(ring, dev_priv, i) {
> >  		i915_record_ring_state(dev, error, ring);
> >  
> >  		error->ring[i].batchbuffer =
> > @@ -1295,6 +1291,8 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
> >  void i915_handle_error(struct drm_device *dev, bool wedged)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	struct intel_ring_buffer *ring;
> > +	int i;
> >  
> >  	i915_capture_error_state(dev);
> >  	i915_report_and_clear_eir(dev);
> > @@ -1306,11 +1304,8 @@ void i915_handle_error(struct drm_device *dev, bool wedged)
> >  		/*
> >  		 * Wakeup waiting processes so they don't hang
> >  		 */
> > -		wake_up_all(&dev_priv->ring[RCS].irq_queue);
> > -		if (HAS_BSD(dev))
> > -			wake_up_all(&dev_priv->ring[VCS].irq_queue);
> > -		if (HAS_BLT(dev))
> > -			wake_up_all(&dev_priv->ring[BCS].irq_queue);
> > +		for_each_ring(ring, dev_priv, i)
> > +			wake_up_all(&ring->irq_queue);
> >  	}
> >  
> >  	queue_work(dev_priv->wq, &dev_priv->error_work);
> > @@ -1515,11 +1510,6 @@ ring_last_seqno(struct intel_ring_buffer *ring)
> >  
> >  static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
> >  {
> > -	/* We don't check whether the ring even exists before calling this
> > -	 * function. Hence check whether it's initialized. */
> > -	if (ring->obj == NULL)
> > -		return true;
> > -
> >  	if (list_empty(&ring->request_list) ||
> >  	    i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
> >  		/* Issue a wake-up to catch stuck h/w. */
> > @@ -1553,26 +1543,25 @@ static bool i915_hangcheck_hung(struct drm_device *dev)
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> >  
> >  	if (dev_priv->hangcheck_count++ > 1) {
> > +		bool hung = true;
> > +
> >  		DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
> >  		i915_handle_error(dev, true);
> >  
> >  		if (!IS_GEN2(dev)) {
> > +			struct intel_ring_buffer *ring;
> > +			int i;
> > +
> >  			/* Is the chip hanging on a WAIT_FOR_EVENT?
> >  			 * If so we can simply poke the RB_WAIT bit
> >  			 * and break the hang. This should work on
> >  			 * all but the second generation chipsets.
> >  			 */
> > -			if (kick_ring(&dev_priv->ring[RCS]))
> > -				return false;
> > -
> > -			if (HAS_BSD(dev) && kick_ring(&dev_priv->ring[VCS]))
> > -				return false;
> > -
> > -			if (HAS_BLT(dev) && kick_ring(&dev_priv->ring[BCS]))
> > -				return false;
> > +			for_each_ring(ring, dev_priv, i)
> > +				hung &= !kick_ring(ring);
> >  		}
> >  
> > -		return true;
> > +		return hung;
> >  	}
> >  
> >  	return false;
> > @@ -1588,16 +1577,23 @@ void i915_hangcheck_elapsed(unsigned long data)
> >  {
> >  	struct drm_device *dev = (struct drm_device *)data;
> >  	drm_i915_private_t *dev_priv = dev->dev_private;
> > -	uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
> > -	bool err = false;
> > +	uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
> > +	struct intel_ring_buffer *ring;
> > +	bool err = false, idle;
> > +	int i;
> >  
> >  	if (!i915_enable_hangcheck)
> >  		return;
> >  
> > +	memset(acthd, 0, sizeof(acthd));
> > +	idle = true;
> > +	for_each_ring(ring, dev_priv, i) {
> > +	    idle &= i915_hangcheck_ring_idle(ring, &err);
> > +	    acthd[i] = intel_ring_get_active_head(ring);
> > +	}
> > +
> >  	/* If all work is done then ACTHD clearly hasn't advanced. */
> > -	if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) &&
> > -	    i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) &&
> > -	    i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) {
> > +	if (idle) {
> >  		if (err) {
> >  			if (i915_hangcheck_hung(dev))
> >  				return;
> > @@ -1616,15 +1612,8 @@ void i915_hangcheck_elapsed(unsigned long data)
> >  		instdone = I915_READ(INSTDONE_I965);
> >  		instdone1 = I915_READ(INSTDONE1);
> >  	}
> > -	acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
> > -	acthd_bsd = HAS_BSD(dev) ?
> > -		intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
> > -	acthd_blt = HAS_BLT(dev) ?
> > -		intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
> >  
> > -	if (dev_priv->last_acthd == acthd &&
> > -	    dev_priv->last_acthd_bsd == acthd_bsd &&
> > -	    dev_priv->last_acthd_blt == acthd_blt &&
> > +	if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
> >  	    dev_priv->last_instdone == instdone &&
> >  	    dev_priv->last_instdone1 == instdone1) {
> >  		if (i915_hangcheck_hung(dev))
> > @@ -1632,9 +1621,7 @@ void i915_hangcheck_elapsed(unsigned long data)
> >  	} else {
> >  		dev_priv->hangcheck_count = 0;
> >  
> > -		dev_priv->last_acthd = acthd;
> > -		dev_priv->last_acthd_bsd = acthd_bsd;
> > -		dev_priv->last_acthd_blt = acthd_blt;
> > +		memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
> >  		dev_priv->last_instdone = instdone;
> >  		dev_priv->last_instdone1 = instdone1;
> >  	}
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 8f8d1da..8e79ff6 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -2326,6 +2326,7 @@ int intel_enable_rc6(const struct drm_device *dev)
> >  
> >  void gen6_enable_rps(struct drm_i915_private *dev_priv)
> >  {
> > +	struct intel_ring_buffer *ring;
> >  	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
> >  	u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
> >  	u32 pcu_mbox, rc6_mask = 0;
> > @@ -2360,8 +2361,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
> >  	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
> >  	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
> >  
> > -	for (i = 0; i < I915_NUM_RINGS; i++)
> > -		I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10);
> > +	for_each_ring(ring, dev_priv, i)
> > +		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
> >  
> >  	I915_WRITE(GEN6_RC_SLEEP, 0);
> >  	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
> > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> > index baba757..55d3da2 100644
> > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> > @@ -119,6 +119,12 @@ struct  intel_ring_buffer {
> >  	void *private;
> >  };
> >  
> > +static inline bool
> > +intel_ring_initialized(struct intel_ring_buffer *ring)
> > +{
> > +	return ring->obj != NULL;
> > +}
> > +
> >  static inline unsigned
> >  intel_ring_flag(struct intel_ring_buffer *ring)
> >  {
> 
> 
> 
> -- 
> Ben Widawsky, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

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

end of thread, other threads:[~2012-05-13 13:34 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-05-11 13:29 [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Chris Wilson
2012-05-11 13:29 ` [PATCH 2/3] drm/i915: Check whether the ring is initialised prior to dispatch Chris Wilson
2012-05-11 19:53   ` Ben Widawsky
2012-05-11 13:29 ` [PATCH 3/3] drm/i915: Replace the feature tests for BLT/BSD with ring init checks Chris Wilson
2012-05-11 19:58   ` Ben Widawsky
2012-05-11 20:24     ` Chris Wilson
2012-05-11 19:46 ` [PATCH 1/3] drm/i915: Introduce for_each_ring() macro Ben Widawsky
2012-05-13 13:35   ` Daniel Vetter

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.