All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/i915: new blitter ring support from Sandybridge
@ 2010-10-12  8:13 Zhenyu Wang
  2010-10-12  8:13 ` [PATCH] intel: " Zhenyu Wang
  2010-10-12  8:34 ` [PATCH] drm/i915: " Chris Wilson
  0 siblings, 2 replies; 4+ messages in thread
From: Zhenyu Wang @ 2010-10-12  8:13 UTC (permalink / raw)
  To: intel-gfx

This adds new ring for blitter engine starting from Sandybridge.

Patch is against 2.6.36-rc kernel. As I haven't been able to find
out all regressions on drm-intel-next yet, which made KMS totally fail
on SNB now. I just base on current upstream tip, so I can see the testing
result.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |   10 ++
 drivers/gpu/drm/i915/i915_dma.c         |    5 +
 drivers/gpu/drm/i915/i915_drv.c         |    2 +
 drivers/gpu/drm/i915/i915_drv.h         |    5 +
 drivers/gpu/drm/i915/i915_gem.c         |   65 +++++++++++++--
 drivers/gpu/drm/i915/i915_gem_evict.c   |   85 +++++++++++++++++--
 drivers/gpu/drm/i915/i915_irq.c         |   26 +++++-
 drivers/gpu/drm/i915/i915_reg.h         |   11 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.c |  139 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h |    1 +
 include/drm/i915_drm.h                  |    2 +
 11 files changed, 333 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 5e43d70..eb82af9 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -43,6 +43,7 @@
 #define ACTIVE_LIST	1
 #define FLUSHING_LIST	2
 #define INACTIVE_LIST	3
+#define BLIT_LIST	4
 
 static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv)
 {
@@ -80,6 +81,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 		lock = &dev_priv->mm.active_list_lock;
 		head = &dev_priv->render_ring.active_list;
 		break;
+	case BLIT_LIST:
+		seq_printf(m, "BLIT:\n");
+		head = &dev_priv->blit_ring.active_list;
+		break;
 	case INACTIVE_LIST:
 		seq_printf(m, "Inactive:\n");
 		head = &dev_priv->mm.inactive_list;
@@ -242,6 +247,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 			   I915_READ(GTIIR));
 		seq_printf(m, "Graphics Interrupt mask:		%08x\n",
 			   I915_READ(GTIMR));
+		if (HAS_BLIT_SPLIT(dev)) {
+			seq_printf(m, "Blitter Interrupt mask:		%08x\n",
+				   I915_READ(GEN6_BLITTER_IMR));
+		}
 	}
 	seq_printf(m, "Interrupts received: %d\n",
 		   atomic_read(&dev_priv->irq_received));
@@ -826,6 +835,7 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
 	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
+	{"i915_gem_blit_active", i915_gem_object_list_info, 0, (void *) BLIT_LIST},
 	{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
 	{"i915_gem_request", i915_gem_request_info, 0},
 	{"i915_gem_seqno", i915_gem_seqno_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c74e4e8..b060a35 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -135,6 +135,8 @@ static int i915_dma_cleanup(struct drm_device * dev)
 	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
 	if (HAS_BSD(dev))
 		intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+	if (HAS_BLIT_SPLIT(dev))
+		intel_cleanup_ring_buffer(dev, &dev_priv->blit_ring);
 	mutex_unlock(&dev->struct_mutex);
 
 	/* Clear the HWS virtual address at teardown */
@@ -765,6 +767,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_BSD:
 		value = HAS_BSD(dev);
 		break;
+	case I915_PARAM_HAS_BLIT_SPLIT:
+		value = HAS_BLIT_SPLIT(dev);
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 6dbe14c..0c08404 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -136,11 +136,13 @@ static const struct intel_device_info intel_ironlake_m_info = {
 static const struct intel_device_info intel_sandybridge_d_info = {
 	.gen = 6, .is_i965g = 1, .is_i9xx = 1,
 	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_blit_split = 1,
 };
 
 static const struct intel_device_info intel_sandybridge_m_info = {
 	.gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1,
 	.need_gfx_hws = 1, .has_hotplug = 1,
+	.has_blit_split = 1,
 };
 
 static const struct pci_device_id pciidlist[] = {		/* aka */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index af4a263..3a98bea 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -212,6 +212,7 @@ struct intel_device_info {
 	u8 has_pipe_cxsr : 1;
 	u8 has_hotplug : 1;
 	u8 cursor_needs_physical : 1;
+	u8 has_blit_split : 1;
 };
 
 enum no_fbc_reason {
@@ -244,6 +245,7 @@ typedef struct drm_i915_private {
 	struct pci_dev *bridge_dev;
 	struct intel_ring_buffer render_ring;
 	struct intel_ring_buffer bsd_ring;
+	struct intel_ring_buffer blit_ring;
 	uint32_t next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
@@ -292,6 +294,7 @@ typedef struct drm_i915_private {
 	u32 flush_rings;
 #define FLUSH_RENDER_RING	0x1
 #define FLUSH_BSD_RING		0x2
+#define FLUSH_BLIT_RING		0x3
 
 	/* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 75 /* in jiffies */
@@ -1191,6 +1194,8 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove
 #define HAS_BSD(dev)            (IS_IRONLAKE(dev) || IS_G4X(dev))
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
+#define HAS_BLIT_SPLIT(dev)	(INTEL_INFO(dev)->has_blit_split)
+
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 90b1d67..276f456 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1797,6 +1797,8 @@ i915_gem_retire_requests(struct drm_device *dev)
 	i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
 	if (HAS_BSD(dev))
 		i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
+	if (HAS_BLIT_SPLIT(dev))
+		i915_gem_retire_requests_ring(dev, &dev_priv->blit_ring);
 }
 
 void
@@ -1815,7 +1817,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	if (!dev_priv->mm.suspended &&
 		(!list_empty(&dev_priv->render_ring.request_list) ||
 			(HAS_BSD(dev) &&
-			 !list_empty(&dev_priv->bsd_ring.request_list))))
+			 !list_empty(&dev_priv->bsd_ring.request_list)) ||
+			(HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.request_list))))
 		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
 	mutex_unlock(&dev->struct_mutex);
 }
@@ -1851,13 +1854,11 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 		ring->user_irq_get(dev, ring);
 		if (interruptible)
 			ret = wait_event_interruptible(ring->irq_queue,
-				i915_seqno_passed(
-					ring->get_gem_seqno(dev, ring), seqno)
+				i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)
 				|| atomic_read(&dev_priv->mm.wedged));
 		else
 			wait_event(ring->irq_queue,
-				i915_seqno_passed(
-					ring->get_gem_seqno(dev, ring), seqno)
+				i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)
 				|| atomic_read(&dev_priv->mm.wedged));
 
 		ring->user_irq_put(dev, ring);
@@ -1910,6 +1911,11 @@ i915_gem_flush(struct drm_device *dev,
 		dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring,
 				invalidate_domains,
 				flush_domains);
+
+	if (HAS_BLIT_SPLIT(dev))
+		dev_priv->blit_ring.flush(dev, &dev_priv->blit_ring,
+					  invalidate_domains,
+					  flush_domains);
 }
 
 /**
@@ -2032,7 +2038,8 @@ i915_gpu_idle(struct drm_device *dev)
 	lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->render_ring.active_list) &&
 		       (!HAS_BSD(dev) ||
-			list_empty(&dev_priv->bsd_ring.active_list)));
+			list_empty(&dev_priv->bsd_ring.active_list)) &&
+		       (!HAS_BLIT_SPLIT(dev) || list_empty(&dev_priv->blit_ring.active_list)));
 	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	if (lists_empty)
@@ -2057,6 +2064,16 @@ i915_gpu_idle(struct drm_device *dev)
 			return ret;
 	}
 
+	if (HAS_BLIT_SPLIT(dev)) {
+		seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS,
+					  &dev_priv->blit_ring);
+		if (seqno2 == 0)
+			return -ENOMEM;
+
+		ret = i915_wait_request(dev, seqno2, &dev_priv->blit_ring);
+		if (ret)
+			return ret;
+	}
 
 	return ret;
 }
@@ -3034,6 +3051,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
 			dev_priv->flush_rings |= FLUSH_RENDER_RING;
 		else if (obj_priv->ring == &dev_priv->bsd_ring)
 			dev_priv->flush_rings |= FLUSH_BSD_RING;
+		else if (obj_priv->ring == &dev_priv->blit_ring)
+			dev_priv->flush_rings |= FLUSH_BLIT_RING;
 	}
 
 	dev->invalidate_domains |= invalidate_domains;
@@ -3573,6 +3592,12 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			return -EINVAL;
 		}
 		ring = &dev_priv->bsd_ring;
+	} else if (args->flags & I915_EXEC_BLIT){
+		if (!HAS_BLIT_SPLIT(dev)) {
+			DRM_ERROR("wrong ring for blit!\n");
+			return -EINVAL;
+		}
+		ring = &dev_priv->blit_ring;
 	} else {
 		ring = &dev_priv->render_ring;
 	}
@@ -3780,6 +3805,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			(void)i915_add_request(dev, file_priv,
 					       dev->flush_domains,
 					       &dev_priv->bsd_ring);
+		if (dev_priv->flush_rings & FLUSH_BLIT_RING)
+			(void)i915_add_request(dev, file_priv,
+					       dev->flush_domains,
+					       &dev_priv->blit_ring);
+	
 	}
 
 	for (i = 0; i < args->buffer_count; i++) {
@@ -4398,7 +4428,8 @@ i915_gem_idle(struct drm_device *dev)
 	if (dev_priv->mm.suspended ||
 			(dev_priv->render_ring.gem_object == NULL) ||
 			(HAS_BSD(dev) &&
-			 dev_priv->bsd_ring.gem_object == NULL)) {
+			 dev_priv->bsd_ring.gem_object == NULL) ||
+			(HAS_BLIT_SPLIT(dev) && !dev_priv->blit_ring.gem_object)) {
 		mutex_unlock(&dev->struct_mutex);
 		return 0;
 	}
@@ -4529,10 +4560,20 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
 			goto cleanup_render_ring;
 	}
 
+	if (HAS_BLIT_SPLIT(dev)) {
+		dev_priv->blit_ring = blit_ring;
+		ret = intel_init_ring_buffer(dev, &dev_priv->blit_ring);
+		if (ret)
+			goto cleanup_bsd_ring;
+	}
+
 	dev_priv->next_seqno = 1;
 
 	return 0;
 
+cleanup_bsd_ring:
+	if (HAS_BSD(dev))
+		intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
 cleanup_render_ring:
 	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
 cleanup_pipe_control:
@@ -4549,6 +4590,8 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 	intel_cleanup_ring_buffer(dev, &dev_priv->render_ring);
 	if (HAS_BSD(dev))
 		intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring);
+	if (HAS_BLIT_SPLIT(dev))
+		intel_cleanup_ring_buffer(dev, &dev_priv->blit_ring);
 	if (HAS_PIPE_CONTROL(dev))
 		i915_gem_cleanup_pipe_control(dev);
 }
@@ -4580,12 +4623,14 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	spin_lock(&dev_priv->mm.active_list_lock);
 	BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
 	BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
+	BUG_ON(HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.active_list));
 	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
 	BUG_ON(!list_empty(&dev_priv->render_ring.request_list));
 	BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
+	BUG_ON(HAS_BLIT_SPLIT(dev) && !list_empty(&dev_priv->blit_ring.request_list));
 	mutex_unlock(&dev->struct_mutex);
 
 	ret = drm_irq_install(dev);
@@ -4645,6 +4690,10 @@ i915_gem_load(struct drm_device *dev)
 		INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list);
 		INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list);
 	}
+	if (HAS_BLIT_SPLIT(dev)) {
+		INIT_LIST_HEAD(&dev_priv->blit_ring.active_list);
+		INIT_LIST_HEAD(&dev_priv->blit_ring.request_list);
+	}
 	for (i = 0; i < 16; i++)
 		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
@@ -4894,6 +4943,8 @@ i915_gpu_is_active(struct drm_device *dev)
 		      list_empty(&dev_priv->render_ring.active_list);
 	if (HAS_BSD(dev))
 		lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
+	if (HAS_BLIT_SPLIT(dev))
+		lists_empty &= list_empty(&dev_priv->blit_ring.active_list);
 	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	return !lists_empty;
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 5c428fa..88eed61 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -34,17 +34,87 @@
 static struct drm_i915_gem_object *
 i915_gem_next_active_object(struct drm_device *dev,
 			    struct list_head **render_iter,
-			    struct list_head **bsd_iter)
+			    struct list_head **bsd_iter,
+			    struct list_head **blit_iter)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *render_obj = NULL, *bsd_obj = NULL;
+	struct drm_i915_gem_object *blit_obj = NULL;
 
 	if (*render_iter != &dev_priv->render_ring.active_list)
 		render_obj = list_entry(*render_iter,
 					struct drm_i915_gem_object,
 					list);
 
-	if (HAS_BSD(dev)) {
+	/* It's true that chip has splitted blit also has BSD. */
+	if (HAS_BLIT_SPLIT(dev)) {
+		u32 render_seq, blit_seq, bsd_seq;
+
+		if (*blit_iter != &dev_priv->blit_ring.active_list)
+			blit_obj = list_entry(*blit_iter,
+					     struct drm_i915_gem_object,
+					     list);
+
+		if (*bsd_iter != &dev_priv->bsd_ring.active_list)
+			bsd_obj = list_entry(*bsd_iter,
+					     struct drm_i915_gem_object,
+					     list);
+
+		/* last_rendering_seqno never could be 0 */
+
+		if (!render_obj)
+			render_seq = 0;
+		else
+			render_seq = render_obj->last_rendering_seqno;
+
+		if (!blit_obj)
+			blit_seq = 0;
+		else
+			blit_seq = blit_obj->last_rendering_seqno;
+
+		if (!bsd_obj)
+			bsd_seq = 0;
+		else
+			bsd_seq = bsd_obj->last_rendering_seqno;
+
+		/* any two null return the third */
+		if (render_seq == blit_seq)
+			return bsd_obj;
+		else if (render_seq == bsd_seq)
+			return blit_obj;
+		else if (blit_seq == bsd_seq)
+			return render_obj;
+
+		/* then only 1 null possible */
+		if (!render_seq) { 
+			if (blit_seq < bsd_seq)
+				return blit_obj;
+			else
+				return bsd_obj;
+		}
+		if (!blit_seq) {
+		       	if (render_seq < bsd_seq)
+				return render_obj;
+			else
+				return bsd_obj;
+		}
+		if (!bsd_seq) {
+		        if (blit_seq < render_seq)
+				return blit_obj;
+			else
+				return render_obj;
+		}
+
+		/* all three */
+		if (render_seq < bsd_seq && render_seq < blit_seq)
+			return render_obj;
+		if (bsd_seq < render_seq && bsd_seq < blit_seq)
+			return bsd_obj;
+		if (blit_seq < bsd_seq && blit_seq < render_seq)
+			return blit_obj;
+		return NULL; /* shut up gcc */
+
+	} else if (HAS_BSD(dev)) {
 		if (*bsd_iter != &dev_priv->bsd_ring.active_list)
 			bsd_obj = list_entry(*bsd_iter,
 					     struct drm_i915_gem_object,
@@ -83,10 +153,11 @@ mark_free(struct drm_i915_gem_object *obj_priv,
 	return drm_mm_scan_add_block(obj_priv->gtt_space);
 }
 
-#define i915_for_each_active_object(OBJ, R, B) \
+#define i915_for_each_active_object(OBJ, R, B, BLIT) \
 	*(R) = dev_priv->render_ring.active_list.next; \
 	*(B) = dev_priv->bsd_ring.active_list.next; \
-	while (((OBJ) = i915_gem_next_active_object(dev, (R), (B))) != NULL)
+	*(BLIT) = dev_priv->blit_ring.active_list.next; \
+	while (((OBJ) = i915_gem_next_active_object(dev, (R), (B),(BLIT))) != NULL)
 
 int
 i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment)
@@ -94,7 +165,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
 	struct drm_i915_gem_object *obj_priv;
-	struct list_head *render_iter, *bsd_iter;
+	struct list_head *render_iter, *bsd_iter, *blit_iter;
 	int ret = 0;
 
 	i915_gem_retire_requests(dev);
@@ -137,7 +208,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
 	}
 
 	/* Now merge in the soon-to-be-expired objects... */
-	i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) {
+	i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter, &blit_iter) {
 		/* Does the object require an outstanding flush? */
 		if (obj_priv->base.write_domain || obj_priv->pin_count)
 			continue;
@@ -154,7 +225,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen
 		if (mark_free(obj_priv, &unwind_list))
 			goto found;
 	}
-	i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter) {
+	i915_for_each_active_object(obj_priv, &render_iter, &bsd_iter, &blit_iter) {
 		if (! obj_priv->base.write_domain || obj_priv->pin_count)
 			continue;
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 744225e..34be1b9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -312,6 +312,7 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 	u32 de_iir, gt_iir, de_ier, pch_iir;
 	struct drm_i915_master_private *master_priv;
 	struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
+	struct intel_ring_buffer *blit_ring = &dev_priv->blit_ring;
 
 	/* disable master interrupt before clearing iir  */
 	de_ier = I915_READ(DEIER);
@@ -345,6 +346,15 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
 	if (gt_iir & GT_BSD_USER_INTERRUPT)
 		DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
 
+	if (HAS_BLIT_SPLIT(dev) && (gt_iir & GT_BLIT_USER_INTERRUPT)) {
+		u32 seqno = blit_ring->get_gem_seqno(dev, blit_ring);
+		blit_ring->irq_gem_seqno = seqno;
+		trace_i915_gem_request_complete(dev, seqno);
+		DRM_WAKEUP(&dev_priv->blit_ring.irq_queue);
+		dev_priv->hangcheck_count = 0;
+		mod_timer(&dev_priv->hangcheck_timer,
+			  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
+	}
 
 	if (de_iir & DE_GSE)
 		ironlake_opregion_gse_intr(dev);
@@ -1367,6 +1377,12 @@ void i915_hangcheck_elapsed(unsigned long data)
 			missed_wakeup = true;
 		}
 
+		if (HAS_BLIT_SPLIT(dev) && dev_priv->blit_ring.waiting_gem_seqno &&
+		    waitqueue_active(&dev_priv->blit_ring.irq_queue)) {
+			DRM_WAKEUP(&dev_priv->blit_ring.irq_queue);
+			missed_wakeup = true;
+		}
+
 		if (missed_wakeup)
 			DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n");
 		return;
@@ -1436,17 +1452,18 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 	I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
 	(void) I915_READ(DEIER);
 
-	/* Gen6 only needs render pipe_control now */
 	if (IS_GEN6(dev))
-		render_mask = GT_PIPE_NOTIFY;
+		render_mask = GT_PIPE_NOTIFY | GT_BLIT_USER_INTERRUPT;
 
 	dev_priv->gt_irq_mask_reg = ~render_mask;
 	dev_priv->gt_irq_enable_reg = render_mask;
 
 	I915_WRITE(GTIIR, I915_READ(GTIIR));
 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev)) {
 		I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
+		I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT);
+	}
 	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
 	(void) I915_READ(GTIER);
 
@@ -1510,6 +1527,9 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
 	if (HAS_BSD(dev))
 		DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue);
 
+	if (HAS_BLIT_SPLIT(dev))
+		DRM_INIT_WAITQUEUE(&dev_priv->blit_ring.irq_queue);
+
 	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
 
 	if (HAS_PCH_SPLIT(dev))
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4f5e155..209c15b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -192,6 +192,7 @@
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
 #define   MI_STORE_DWORD_INDEX_SHIFT 2
 #define MI_LOAD_REGISTER_IMM	MI_INSTR(0x22, 1)
+#define MI_FLUSH_DW		MI_INSTR(0x26, 2)
 #define MI_BATCH_BUFFER		MI_INSTR(0x30, 1)
 #define   MI_BATCH_NON_SECURE	(1)
 #define   MI_BATCH_NON_SECURE_I965 (1<<8)
@@ -476,6 +477,14 @@
 #define BSD_RING_ACTHD         0x04074
 #define BSD_HWS_PGA            0x04080
 
+/* Blit ring */
+#define BLIT_RING_TAIL          0x22030
+#define BLIT_RING_HEAD          0x22034
+#define BLIT_RING_START         0x22038
+#define BLIT_RING_CTL           0x2203c
+#define BLIT_RING_ACTHD         0x22074
+#define BLIT_HWS_PGA            0x24080
+
 /*
  * Framebuffer compression (915+ only)
  */
@@ -2516,7 +2525,7 @@
 #define GT_SYNC_STATUS          (1 << 2)
 #define GT_USER_INTERRUPT       (1 << 0)
 #define GT_BSD_USER_INTERRUPT   (1 << 5)
-
+#define GT_BLIT_USER_INTERRUPT	(1 << 22)
 
 #define GTISR   0x44010
 #define GTIMR   0x44014
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index cb3508f..dac1c61 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -488,6 +488,109 @@ bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
 	return 0;
 }
 
+/* blit */
+static void blit_setup_status_page(struct drm_device *dev,
+				   struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	I915_WRITE(BLIT_HWS_PGA, ring->status_page.gfx_addr);
+	I915_READ(BLIT_HWS_PGA);
+}
+
+void blit_ring_flush(struct drm_device *dev,
+		     struct intel_ring_buffer *ring,
+		     u32 invalidate_domains,
+		     u32 flush_domains)
+{
+	intel_ring_begin(dev, ring, 4);
+	intel_ring_emit(dev, ring, MI_FLUSH_DW);
+	intel_ring_emit(dev, ring, 0);
+	intel_ring_emit(dev, ring, 0);
+	intel_ring_emit(dev, ring, 0);
+	intel_ring_advance(dev, ring);
+}
+
+static inline unsigned int blit_ring_get_head(struct drm_device *dev,
+					      struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	return I915_READ(BLIT_RING_HEAD) & HEAD_ADDR;
+}
+
+static inline unsigned int blit_ring_get_tail(struct drm_device *dev,
+					      struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	return I915_READ(BLIT_RING_TAIL) & TAIL_ADDR;
+}
+
+static inline unsigned int blit_ring_get_active_head(struct drm_device *dev,
+						     struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	return I915_READ(BLIT_RING_ACTHD);
+}
+
+static inline void blit_ring_advance_ring(struct drm_device *dev,
+					  struct intel_ring_buffer *ring)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	I915_WRITE(BLIT_RING_TAIL, ring->tail);
+}
+
+static u32 blit_ring_add_request(struct drm_device *dev,
+				struct intel_ring_buffer *ring,
+				struct drm_file *file_priv,
+				u32 flush_domains)
+{
+	u32 seqno;
+
+	seqno = i915_gem_get_seqno(dev);
+
+	intel_ring_begin(dev, ring, 4);
+	intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX);
+	intel_ring_emit(dev, ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+	intel_ring_emit(dev, ring, seqno);
+	intel_ring_emit(dev, ring, MI_USER_INTERRUPT);
+	intel_ring_advance(dev, ring);
+
+	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
+
+	return seqno;
+}
+
+static void blit_ring_get_user_irq(struct drm_device *dev,
+				   struct intel_ring_buffer *ring)
+{
+	/* do nothing */
+}
+static void blit_ring_put_user_irq(struct drm_device *dev,
+				   struct intel_ring_buffer *ring)
+{
+	/* do nothing */
+}
+
+static u32 blit_ring_get_gem_seqno(struct drm_device *dev,
+				   struct intel_ring_buffer *ring)
+{
+	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static int blit_ring_dispatch_gem_execbuffer(struct drm_device *dev,
+					     struct intel_ring_buffer *ring,
+					     struct drm_i915_gem_execbuffer2 *exec,
+					     struct drm_clip_rect *cliprects,
+					     uint64_t exec_offset)
+{
+	uint32_t exec_start;
+	exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
+	intel_ring_begin(dev, ring, 2);
+	intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START |
+			(2 << 6) | MI_BATCH_NON_SECURE_I965);
+	intel_ring_emit(dev, ring, exec_start);
+	intel_ring_advance(dev, ring);
+	return 0;
+}
 
 static int
 render_ring_dispatch_gem_execbuffer(struct drm_device *dev,
@@ -866,3 +969,39 @@ struct intel_ring_buffer bsd_ring = {
 	.status_page		= {NULL, 0, NULL},
 	.map			= {0,}
 };
+
+struct intel_ring_buffer blit_ring = {
+	.name                   = "blit ring",
+	.regs			= {
+		.ctl = BLIT_RING_CTL,
+		.head = BLIT_RING_HEAD,
+		.tail = BLIT_RING_TAIL,
+		.start = BLIT_RING_START
+	},
+	.ring_flag		= I915_EXEC_BLIT,
+	.size			= 32 * PAGE_SIZE,
+	.alignment		= PAGE_SIZE,
+	.virtual_start		= NULL,
+	.dev			= NULL,
+	.gem_object		= NULL,
+	.head			= 0,
+	.tail			= 0,
+	.space			= 0,
+	.user_irq_refcount	= 0,
+	.irq_gem_seqno		= 0,
+	.waiting_gem_seqno	= 0,
+	.setup_status_page	= blit_setup_status_page,
+	.init			= init_ring_common,
+	.get_head		= blit_ring_get_head,
+	.get_tail		= blit_ring_get_tail,
+	.get_active_head	= blit_ring_get_active_head,
+	.advance_ring		= blit_ring_advance_ring,
+	.flush			= blit_ring_flush,
+	.add_request		= blit_ring_add_request,
+	.get_gem_seqno		= blit_ring_get_gem_seqno,
+	.user_irq_get		= blit_ring_get_user_irq,
+	.user_irq_put		= blit_ring_put_user_irq,
+	.dispatch_gem_execbuffer = blit_ring_dispatch_gem_execbuffer,
+	.status_page		= {NULL, 0, NULL},
+	.map			= {0,}
+};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 525e7d3..d6d8a7b 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -127,5 +127,6 @@ u32 intel_ring_get_seqno(struct drm_device *dev,
 
 extern struct intel_ring_buffer render_ring;
 extern struct intel_ring_buffer bsd_ring;
+extern struct intel_ring_buffer blit_ring;
 
 #endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index e41c74f..087879d 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -286,6 +286,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PAGEFLIPPING	 8
 #define I915_PARAM_HAS_EXECBUF2          9
 #define I915_PARAM_HAS_BSD		 10
+#define I915_PARAM_HAS_BLIT_SPLIT	 11
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -629,6 +630,7 @@ struct drm_i915_gem_execbuffer2 {
 	__u64 cliprects_ptr;
 #define I915_EXEC_RENDER                 (1<<0)
 #define I915_EXEC_BSD                    (1<<1)
+#define I915_EXEC_BLIT                   (1<<2)
 	__u64 flags;
 	__u64 rsvd1;
 	__u64 rsvd2;
-- 
1.7.0.4

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

* [PATCH] intel: new blitter ring support from Sandybridge
  2010-10-12  8:13 [PATCH] drm/i915: new blitter ring support from Sandybridge Zhenyu Wang
@ 2010-10-12  8:13 ` Zhenyu Wang
  2010-10-12  8:34 ` [PATCH] drm/i915: " Chris Wilson
  1 sibling, 0 replies; 4+ messages in thread
From: Zhenyu Wang @ 2010-10-12  8:13 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
---
 include/drm/i915_drm.h   |    2 ++
 intel/intel_bufmgr_gem.c |   12 +++++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 7594413..694fb24 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -276,6 +276,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PAGEFLIPPING	 8
 #define I915_PARAM_HAS_EXECBUF2          9
 #define I915_PARAM_HAS_BSD		 10
+#define I915_PARAM_HAS_BLIT_SPLIT	 11
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -619,6 +620,7 @@ struct drm_i915_gem_execbuffer2 {
 	__u64 cliprects_ptr;
 #define I915_EXEC_RENDER                 (1<<0)
 #define I915_EXEC_BSD                    (1<<1)
+#define I915_EXEC_BLIT                   (1<<2)
 	__u64 flags;
 	__u64 rsvd1;
 	__u64 rsvd2;
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 60174e1..57229e9 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -1545,7 +1545,8 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
 	struct drm_i915_gem_execbuffer2 execbuf;
 	int ret, i;
 
-	if ((ring_flag != I915_EXEC_RENDER) && (ring_flag != I915_EXEC_BSD))
+	if ((ring_flag != I915_EXEC_RENDER) && (ring_flag != I915_EXEC_BSD) &&
+	    (ring_flag != I915_EXEC_BLIT))
 		return -EINVAL;
 
 	pthread_mutex_lock(&bufmgr_gem->lock);
@@ -2054,7 +2055,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 	struct drm_i915_gem_get_aperture aperture;
 	drm_i915_getparam_t gp;
 	int ret;
-	int exec2 = 0, has_bsd = 0;
+	int exec2 = 0, has_bsd = 0, blit_split = 0;
 
 	bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
 	if (bufmgr_gem == NULL)
@@ -2110,6 +2111,11 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 	if (!ret)
 		has_bsd = 1;
 
+	gp.param = I915_PARAM_HAS_BLIT_SPLIT;
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	if (!ret)
+		blit_split = *gp.value;
+
 	if (bufmgr_gem->gen < 4) {
 		gp.param = I915_PARAM_NUM_FENCES_AVAIL;
 		gp.value = &bufmgr_gem->available_fences;
@@ -2165,7 +2171,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 	/* Use the new one if available */
 	if (exec2) {
 		bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec2;
-		if (has_bsd)
+		if (has_bsd || blit_split)
 			bufmgr_gem->bufmgr.bo_mrb_exec = drm_intel_gem_bo_mrb_exec2;
 	} else
 		bufmgr_gem->bufmgr.bo_exec = drm_intel_gem_bo_exec;
-- 
1.7.0.4

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

* Re: [PATCH] drm/i915: new blitter ring support from Sandybridge
  2010-10-12  8:13 [PATCH] drm/i915: new blitter ring support from Sandybridge Zhenyu Wang
  2010-10-12  8:13 ` [PATCH] intel: " Zhenyu Wang
@ 2010-10-12  8:34 ` Chris Wilson
  2010-10-12  8:55   ` Zhenyu Wang
  1 sibling, 1 reply; 4+ messages in thread
From: Chris Wilson @ 2010-10-12  8:34 UTC (permalink / raw)
  To: Zhenyu Wang, intel-gfx

On Tue, 12 Oct 2010 16:13:51 +0800, Zhenyu Wang <zhenyuw@linux.intel.com> wrote:
> This adds new ring for blitter engine starting from Sandybridge.

Thanks, look fairly straightforward. The messy parts are a clear reminder
that I intended to clean up some areas for multiple rings.

* bikeshedding

s/HAS_BLIT_SPLIT/HAS_BLT/ -- the documentation has ingrained BLT engine
into my head (and I hope they haven't changed on a whim for snb)

After initialisation we should not need to care about HAS_BSD/HAS_BLT and
just test whether the ring is initialised or active (depending upon op).
That should dramatically reduce the number of tests in our code and
hopefully lead to further simplifications.

Unified request list (along with per-ring lists) will sort out the mess in
i915_gem_evict and also solve the wrap-around issue.

So no get/put irq again?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH] drm/i915: new blitter ring support from Sandybridge
  2010-10-12  8:34 ` [PATCH] drm/i915: " Chris Wilson
@ 2010-10-12  8:55   ` Zhenyu Wang
  0 siblings, 0 replies; 4+ messages in thread
From: Zhenyu Wang @ 2010-10-12  8:55 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 1387 bytes --]

On 2010.10.12 09:34:10 +0100, Chris Wilson wrote:
> On Tue, 12 Oct 2010 16:13:51 +0800, Zhenyu Wang <zhenyuw@linux.intel.com> wrote:
> > This adds new ring for blitter engine starting from Sandybridge.
> 
> Thanks, look fairly straightforward. The messy parts are a clear reminder
> that I intended to clean up some areas for multiple rings.
> 
> * bikeshedding
> 
> s/HAS_BLIT_SPLIT/HAS_BLT/ -- the documentation has ingrained BLT engine
> into my head (and I hope they haven't changed on a whim for snb)

ok, BLT looks better.

> 
> After initialisation we should not need to care about HAS_BSD/HAS_BLT and
> just test whether the ring is initialised or active (depending upon op).
> That should dramatically reduce the number of tests in our code and
> hopefully lead to further simplifications.
> 
> Unified request list (along with per-ring lists) will sort out the mess in
> i915_gem_evict and also solve the wrap-around issue.
> 
> So no get/put irq again?

yeah, current still uses user_interrupt, that has been unmasked and enabled
from beginning. I just did some copy&paste, it could be fixed to our original
behavior by mask initially and unmask as required, which might involve irq
enable/disable sequence specific on different hw though.

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

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

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

end of thread, other threads:[~2010-10-12  8:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-12  8:13 [PATCH] drm/i915: new blitter ring support from Sandybridge Zhenyu Wang
2010-10-12  8:13 ` [PATCH] intel: " Zhenyu Wang
2010-10-12  8:34 ` [PATCH] drm/i915: " Chris Wilson
2010-10-12  8:55   ` Zhenyu Wang

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.