diff mbox

[37/66] drm/i915: Create VMAs (part 6) - finish error plumbing

Message ID 1372375867-1003-38-git-send-email-ben@bwidawsk.net (mailing list archive)
State New, archived
Headers show

Commit Message

Ben Widawsky June 27, 2013, 11:30 p.m. UTC
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
---
 drivers/gpu/drm/i915/i915_irq.c | 53 ++++++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 16 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 28880bf..e1653fd 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1499,6 +1499,7 @@  static void i915_get_extra_instdone(struct drm_device *dev,
 static struct drm_i915_error_object *
 i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 			       struct drm_i915_gem_object *src,
+			       struct i915_address_space *vm,
 			       const int num_pages)
 {
 	struct drm_i915_error_object *dst;
@@ -1512,8 +1513,7 @@  i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 	if (dst == NULL)
 		return NULL;
 
-	/* FIXME: must handle per faulty VM */
-	reloc_offset = i915_gem_ggtt_offset(src);
+	reloc_offset = i915_gem_obj_offset(src, vm);
 	for (i = 0; i < num_pages; i++) {
 		unsigned long flags;
 		void *d;
@@ -1565,7 +1565,7 @@  i915_error_object_create_sized(struct drm_i915_private *dev_priv,
 		reloc_offset += PAGE_SIZE;
 	}
 	dst->page_count = num_pages;
-	dst->gtt_offset = i915_gem_ggtt_offset(src);
+	dst->gtt_offset = i915_gem_obj_offset(src, vm);
 
 	return dst;
 
@@ -1575,8 +1575,9 @@  unwind:
 	kfree(dst);
 	return NULL;
 }
-#define i915_error_object_create(dev_priv, src) \
+#define i915_error_object_create(dev_priv, src, vm) \
 	i915_error_object_create_sized((dev_priv), (src), \
+				       vm, \
 				       (src)->base.size>>PAGE_SHIFT)
 
 static void
@@ -1617,14 +1618,14 @@  i915_error_state_free(struct kref *error_ref)
 	kfree(error);
 }
 static void capture_bo(struct drm_i915_error_buffer *err,
-		       struct drm_i915_gem_object *obj)
+		       struct drm_i915_gem_object *obj,
+		       struct i915_address_space *vm)
 {
 	err->size = obj->base.size;
 	err->name = obj->base.name;
 	err->rseqno = obj->last_read_seqno;
 	err->wseqno = obj->last_write_seqno;
-	/* FIXME: plumb the actual context into here to pull the right VM */
-	err->gtt_offset = i915_gem_ggtt_offset(obj);
+	err->gtt_offset = i915_gem_obj_offset(obj, vm);
 	err->read_domains = obj->base.read_domains;
 	err->write_domain = obj->base.write_domain;
 	err->fence_reg = obj->fence_reg;
@@ -1647,7 +1648,7 @@  static u32 capture_active_bo(struct drm_i915_error_buffer *err,
 	int i = 0;
 
 	list_for_each_entry(vma, head, mm_list) {
-		capture_bo(err++, vma->obj);
+		capture_bo(err++, vma->obj, vma->vm);
 		if (++i == count)
 			break;
 	}
@@ -1662,10 +1663,14 @@  static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
 	int i = 0;
 
 	list_for_each_entry(obj, head, global_list) {
+		struct i915_vma *vma;
 		if (obj->pin_count == 0)
 			continue;
 
-		capture_bo(err++, obj);
+		/* Object may be pinned in multiple VMs, just take first */
+		vma = list_first_entry(&obj->vma_list, struct i915_vma,
+				       vma_link);
+		capture_bo(err++, obj, vma->vm);
 		if (++i == count)
 			break;
 	}
@@ -1713,6 +1718,7 @@  i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 	struct i915_vma *vma;
 	struct drm_i915_gem_object *obj;
 	u32 seqno;
+	u32 pp_db;
 
 	if (!ring->get_seqno)
 		return NULL;
@@ -1729,11 +1735,19 @@  i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 		obj = ring->private;
 		if (acthd >= i915_gem_ggtt_offset(obj) &&
 		    acthd < i915_gem_ggtt_offset(obj) + obj->base.size)
-			return i915_error_object_create(dev_priv, obj);
+			return i915_error_object_create(dev_priv, obj,
+							&dev_priv->gtt.base);
 	}
 
+	pp_db = I915_READ(RING_PP_DIR_BASE(ring));
 	seqno = ring->get_seqno(ring, false);
+
 	list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+		struct i915_hw_ppgtt *ppgtt =
+			container_of(vm, struct i915_hw_ppgtt, base);
+		if (!is_i915_ggtt(vm) && pp_db >> 10 != ppgtt->pd_offset)
+			continue;
+
 		list_for_each_entry(vma, &vm->active_list, mm_list) {
 			obj = vma->obj;
 			if (obj->ring != ring)
@@ -1749,7 +1763,7 @@  i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 			 * simplest method to avoid being overwritten by
 			 * userspace.
 			 */
-			return i915_error_object_create(dev_priv, obj);
+			return i915_error_object_create(dev_priv, obj, vm);
 		}
 	}
 
@@ -1806,6 +1820,7 @@  static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
 					   struct drm_i915_error_ring *ering)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct i915_address_space *ggtt = &dev_priv->gtt.base;
 	struct drm_i915_gem_object *obj;
 
 	/* Currently render ring is the only HW context user */
@@ -1813,9 +1828,14 @@  static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
 		return;
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+		if (!i915_gem_obj_bound(obj, ggtt))
+			continue;
+
 		if ((error->ccid & PAGE_MASK) == i915_gem_ggtt_offset(obj)) {
 			ering->ctx = i915_error_object_create_sized(dev_priv,
-								    obj, 1);
+								    obj,
+								    ggtt,
+								    1);
 		}
 	}
 }
@@ -1835,8 +1855,8 @@  static void i915_gem_record_rings(struct drm_device *dev,
 			i915_error_first_batchbuffer(dev_priv, ring);
 
 		error->ring[i].ringbuffer =
-			i915_error_object_create(dev_priv, ring->obj);
-
+			i915_error_object_create(dev_priv, ring->obj,
+						 &dev_priv->gtt.base);
 
 		i915_gem_record_active_context(ring, error, &error->ring[i]);
 
@@ -1912,7 +1932,7 @@  static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
 				     struct drm_i915_error_state *error)
 {
 	struct i915_address_space *vm;
-	int cnt = 0;
+	int cnt = 0, i = 0;
 
 	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
 		cnt++;
@@ -1929,7 +1949,8 @@  static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
 	error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count),
 					 GFP_ATOMIC);
 
-	i915_gem_capture_vm(dev_priv, error, vm, 0);
+	list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+		i915_gem_capture_vm(dev_priv, error, vm, i++);
 }
 
 /**