diff mbox

[RFC,2/8] prime wip: i915

Message ID 1341917871-2512-3-git-send-email-m.b.lankhorst@gmail.com
State New
Headers show

Commit Message

Maarten Lankhorst July 10, 2012, 10:57 a.m. UTC
From: Maarten Lankhorst <maarten.lankhorst@canonical.com>

Export the hardware status page so others can read seqno.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>

---
 drivers/gpu/drm/i915/i915_gem_dmabuf.c     |   29 ++++++++--
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   87 ++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_ringbuffer.c    |   42 ++++++++++++++
 drivers/gpu/drm/i915/intel_ringbuffer.h    |    3 +
 4 files changed, 145 insertions(+), 16 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index aa308e1..d6bcfdc 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -66,12 +66,25 @@  static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
 static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
 {
 	struct drm_i915_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->base.dev;
+
+	mutex_lock(&dev->struct_mutex);
 
 	if (obj->base.export_dma_buf == dma_buf) {
-		/* drop the reference on the export fd holds */
 		obj->base.export_dma_buf = NULL;
-		drm_gem_object_unreference_unlocked(&obj->base);
+	} else {
+		drm_i915_private_t *dev_priv = dev->dev_private;
+		struct intel_ring_buffer *ring;
+		int i;
+
+		for_each_ring(ring, dev_priv, i)
+			WARN_ON(ring->sync_buf == dma_buf);
 	}
+
+	/* drop the reference on the export fd holds */
+	drm_gem_object_unreference(&obj->base);
+
+	mutex_unlock(&dev->struct_mutex);
 }
 
 static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
@@ -129,21 +142,25 @@  static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 
 static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
 {
-	return NULL;
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	return kmap_atomic(obj->pages[page_num]);
 }
 
 static void i915_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
 {
-
+	kunmap_atomic(addr);
 }
+
 static void *i915_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num)
 {
-	return NULL;
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	return kmap(obj->pages[page_num]);
 }
 
 static void i915_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
 {
-
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	kunmap(obj->pages[page_num]);
 }
 
 static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 88e2e11..245340e 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -33,6 +33,7 @@ 
 #include "i915_trace.h"
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
+#include <linux/dma-buf-mgr.h>
 
 struct change_domains {
 	uint32_t invalidate_domains;
@@ -556,7 +557,8 @@  err_unpin:
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			    struct drm_file *file,
-			    struct list_head *objects)
+			    struct list_head *objects,
+			    struct list_head *prime_val)
 {
 	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	struct drm_i915_gem_object *obj;
@@ -564,6 +566,31 @@  i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
 	struct list_head ordered_objects;
 
+	list_for_each_entry(obj, objects, exec_list) {
+		struct dmabufmgr_validate *val;
+
+		if (!(obj->base.import_attach ||
+		      obj->base.export_dma_buf))
+			continue;
+
+		val = kzalloc(sizeof(*val), GFP_KERNEL);
+		if (!val)
+			return -ENOMEM;
+
+		if (obj->base.export_dma_buf)
+			val->bo = obj->base.export_dma_buf;
+		else
+			val->bo = obj->base.import_attach->dmabuf;
+		val->priv = obj;
+		list_add_tail(&val->head, prime_val);
+	}
+
+	if (!list_empty(prime_val)) {
+		ret = dmabufmgr_eu_reserve_buffers(prime_val);
+		if (ret)
+			return ret;
+	}
+
 	INIT_LIST_HEAD(&ordered_objects);
 	while (!list_empty(objects)) {
 		struct drm_i915_gem_exec_object2 *entry;
@@ -712,6 +739,7 @@  i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 				  struct drm_file *file,
 				  struct intel_ring_buffer *ring,
 				  struct list_head *objects,
+				  struct list_head *prime_val,
 				  struct eb_objects *eb,
 				  struct drm_i915_gem_exec_object2 *exec,
 				  int count)
@@ -722,6 +750,16 @@  i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 	int i, total, ret;
 
 	/* We may process another execbuffer during the unlock... */
+
+	if (!list_empty(prime_val))
+		dmabufmgr_eu_backoff_reservation(prime_val);
+	while (!list_empty(prime_val)) {
+		struct dmabufmgr_validate *val;
+		val = list_first_entry(prime_val, typeof(*val), head);
+		list_del(&val->head);
+		kfree(val);
+	}
+
 	while (!list_empty(objects)) {
 		obj = list_first_entry(objects,
 				       struct drm_i915_gem_object,
@@ -786,7 +824,7 @@  i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 		eb_add_object(eb, obj);
 	}
 
-	ret = i915_gem_execbuffer_reserve(ring, file, objects);
+	ret = i915_gem_execbuffer_reserve(ring, file, objects, prime_val);
 	if (ret)
 		goto err;
 
@@ -854,10 +892,10 @@  i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
 	return 0;
 }
 
-
 static int
 i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
-				struct list_head *objects)
+				struct list_head *objects,
+				struct list_head *prime_val)
 {
 	struct drm_i915_gem_object *obj;
 	struct change_domains cd;
@@ -941,7 +979,6 @@  i915_gem_execbuffer_move_to_active(struct list_head *objects,
 		  u32 old_read = obj->base.read_domains;
 		  u32 old_write = obj->base.write_domain;
 
-
 		obj->base.read_domains = obj->base.pending_read_domains;
 		obj->base.write_domain = obj->base.pending_write_domain;
 		obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
@@ -1012,6 +1049,7 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head objects;
+	struct list_head prime_val;
 	struct eb_objects *eb;
 	struct drm_i915_gem_object *batch_obj;
 	struct drm_clip_rect *cliprects = NULL;
@@ -1145,6 +1183,7 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	/* Look up object handles */
 	INIT_LIST_HEAD(&objects);
+	INIT_LIST_HEAD(&prime_val);
 	for (i = 0; i < args->buffer_count; i++) {
 		struct drm_i915_gem_object *obj;
 
@@ -1176,8 +1215,14 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			       struct drm_i915_gem_object,
 			       exec_list);
 
+	if (batch_obj->base.export_dma_buf || batch_obj->base.import_attach) {
+		DRM_DEBUG("Batch buffer should really not be prime..\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
 	/* Move the objects en-masse into the GTT, evicting if necessary. */
-	ret = i915_gem_execbuffer_reserve(ring, file, &objects);
+	ret = i915_gem_execbuffer_reserve(ring, file, &objects, &prime_val);
 	if (ret)
 		goto err;
 
@@ -1186,8 +1231,9 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret) {
 		if (ret == -EFAULT) {
 			ret = i915_gem_execbuffer_relocate_slow(dev, file, ring,
-								&objects, eb,
-								exec,
+								&objects,
+								&prime_val,
+								eb, exec,
 								args->buffer_count);
 			BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 		}
@@ -1203,7 +1249,7 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	}
 	batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND;
 
-	ret = i915_gem_execbuffer_move_to_gpu(ring, &objects);
+	ret = i915_gem_execbuffer_move_to_gpu(ring, &objects, &prime_val);
 	if (ret)
 		goto err;
 
@@ -1227,7 +1273,7 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	    mode != dev_priv->relative_constants_mode) {
 		ret = intel_ring_begin(ring, 4);
 		if (ret)
-				goto err;
+			goto err;
 
 		intel_ring_emit(ring, MI_NOOP);
 		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
@@ -1248,6 +1294,10 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto err;
 
+	ret = dmabufmgr_eu_wait_completed_cpu(&prime_val, true, true);
+	if (ret)
+		goto err;
+
 	trace_i915_gem_ring_dispatch(ring, seqno);
 
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
@@ -1272,8 +1322,25 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 	i915_gem_execbuffer_move_to_active(&objects, ring, seqno);
 	i915_gem_execbuffer_retire_commands(dev, file, ring);
+	if (!list_empty(&prime_val)) {
+		BUG_ON(!ring->sync_buf);
+		WARN_ON_ONCE(seqno == ring->outstanding_lazy_request);
+
+		dmabufmgr_eu_fence_buffer_objects(ring->sync_buf,
+						  ring->sync_seqno_ofs,
+						  seqno, &prime_val);
+	}
+	goto out;
 
 err:
+	dmabufmgr_eu_backoff_reservation(&prime_val);
+out:
+	while (!list_empty(&prime_val)) {
+		struct dmabufmgr_validate *val;
+		val = list_first_entry(&prime_val, typeof(*val), head);
+		list_del(&val->head);
+		kfree(val);
+	}
 	eb_destroy(eb);
 	while (!list_empty(&objects)) {
 		struct drm_i915_gem_object *obj;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index d42d821..24795e1 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -33,6 +33,7 @@ 
 #include "i915_drm.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/dma-buf.h>
 
 /*
  * 965+ support PIPE_CONTROL commands, which provide finer grained control
@@ -383,6 +384,22 @@  init_pipe_control(struct intel_ring_buffer *ring)
 	if (pc->cpu_page == NULL)
 		goto err_unpin;
 
+#ifdef CONFIG_DMA_SHARED_BUFFER
+	if (IS_GEN5(ring->dev)) {
+		struct dma_buf *dmabuf;
+		dmabuf = i915_gem_prime_export(ring->dev, &obj->base, 0);
+		if (IS_ERR(dmabuf)) {
+			ret = PTR_ERR(dmabuf);
+			kunmap(obj->pages[0]);
+			pc->cpu_page = NULL;
+			goto err_unpin;
+		}
+		drm_gem_object_reference(&obj->base);
+		ring->sync_buf = dmabuf;
+		ring->sync_seqno_ofs = 0;
+	}
+#endif
+
 	pc->obj = obj;
 	ring->private = pc;
 	return 0;
@@ -419,6 +436,8 @@  static int init_render_ring(struct intel_ring_buffer *ring)
 	struct drm_device *dev = ring->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret = init_ring_common(ring);
+	if (ret)
+		return ret;
 
 	if (INTEL_INFO(dev)->gen > 3) {
 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
@@ -943,6 +962,14 @@  static void cleanup_status_page(struct intel_ring_buffer *ring)
 	if (obj == NULL)
 		return;
 
+	if (ring->sync_buf) {
+		struct dma_buf *dmabuf;
+
+		dmabuf = ring->sync_buf;
+		ring->sync_buf = NULL;
+		dma_buf_put(dmabuf);
+	}
+
 	kunmap(obj->pages[0]);
 	i915_gem_object_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
@@ -974,6 +1001,21 @@  static int init_status_page(struct intel_ring_buffer *ring)
 	if (ring->status_page.page_addr == NULL) {
 		goto err_unpin;
 	}
+
+#ifdef CONFIG_DMA_SHARED_BUFFER
+	if (!IS_GEN5(ring->dev) || ring->init == init_ring_common) {
+		struct dma_buf *dmabuf;
+		dmabuf = i915_gem_prime_export(dev, &obj->base, 0);
+		if (IS_ERR(dmabuf)) {
+			ret = PTR_ERR(dmabuf);
+			kunmap(obj->pages[0]);
+			goto err_unpin;
+		}
+		drm_gem_object_reference(&obj->base);
+		ring->sync_buf = dmabuf;
+		ring->sync_seqno_ofs = I915_GEM_HWS_INDEX * 4;
+	}
+#endif
 	ring->status_page.obj = obj;
 	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 1d3c81f..c878b14 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -124,6 +124,9 @@  struct  intel_ring_buffer {
 	struct i915_hw_context *default_context;
 	struct drm_i915_gem_object *last_context_obj;
 
+	struct dma_buf *sync_buf;
+	u32 sync_seqno_ofs;
+
 	void *private;
 };