drm/i915: Update error capture for VMs
authorBen Widawsky <ben@bwidawsk.net>
Thu, 1 Aug 2013 00:00:15 +0000 (17:00 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 8 Aug 2013 12:08:37 +0000 (14:08 +0200)
formerly: "drm/i915: Create VMAs (part 4) - Error capture"

Since the active/inactive lists are per VM, we need to modify the error
capture code to be aware of this, and also extend it to capture the
buffers from all the VMs. For now all the code assumes only 1 VM, but it
will become more generic over the next few patches.

NOTE: If the number of VMs in a real world system grows significantly
we'll have to focus on only capturing the guilty VM, or else it's likely
there won't be enough space for error capture.

v2: Squashed in the "part 6" which had dependencies on the mm_list
change. Since I've moved the mm_list change to an earlier point in the
series, we were able to accomplish it here and now.

v3: Rebased over new error capture

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gpu_error.c

index 20becc5500bd8a3c3863d4b37e26ef1ec916c57d..d0cdec81aac3eceaf13e8352665ca1ff7be1d6d0 100644 (file)
@@ -323,8 +323,8 @@ struct drm_i915_error_state {
                u32 purgeable:1;
                s32 ring:4;
                u32 cache_level:2;
-       } *active_bo, *pinned_bo;
-       u32 active_bo_count, pinned_bo_count;
+       } **active_bo, **pinned_bo;
+       u32 *active_bo_count, *pinned_bo_count;
        struct intel_overlay_error_state *overlay;
        struct intel_display_error_state *display;
 };
index fad48b2bb870dfa1c4b4d4810dc4a5ab267c81e1..60393cb9a7c74db89712c171c1294467fd5af443 100644 (file)
@@ -304,13 +304,13 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 
        if (error->active_bo)
                print_error_buffers(m, "Active",
-                                   error->active_bo,
-                                   error->active_bo_count);
+                                   error->active_bo[0],
+                                   error->active_bo_count[0]);
 
        if (error->pinned_bo)
                print_error_buffers(m, "Pinned",
-                                   error->pinned_bo,
-                                   error->pinned_bo_count);
+                                   error->pinned_bo[0],
+                                   error->pinned_bo_count[0]);
 
        for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
                struct drm_i915_error_object *obj;
@@ -775,42 +775,72 @@ static void i915_gem_record_rings(struct drm_device *dev,
        }
 }
 
-static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
-                                    struct drm_i915_error_state *error)
+/* FIXME: Since pin count/bound list is global, we duplicate what we capture per
+ * VM.
+ */
+static void i915_gem_capture_vm(struct drm_i915_private *dev_priv,
+                               struct drm_i915_error_state *error,
+                               struct i915_address_space *vm,
+                               const int ndx)
 {
-       struct i915_address_space *vm = &dev_priv->gtt.base;
-       struct i915_vma *vma;
+       struct drm_i915_error_buffer *active_bo = NULL, *pinned_bo = NULL;
        struct drm_i915_gem_object *obj;
+       struct i915_vma *vma;
        int i;
 
        i = 0;
        list_for_each_entry(vma, &vm->active_list, mm_list)
                i++;
-       error->active_bo_count = i;
+       error->active_bo_count[ndx] = i;
        list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
                if (obj->pin_count)
                        i++;
-       error->pinned_bo_count = i - error->active_bo_count;
+       error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx];
 
        if (i) {
-               error->active_bo = kmalloc(sizeof(*error->active_bo)*i,
-                                          GFP_ATOMIC);
-               if (error->active_bo)
-                       error->pinned_bo =
-                               error->active_bo + error->active_bo_count;
+               active_bo = kmalloc(sizeof(*active_bo)*i, GFP_ATOMIC);
+               if (active_bo)
+                       pinned_bo = active_bo + error->active_bo_count[ndx];
        }
 
-       if (error->active_bo)
-               error->active_bo_count =
-                       capture_active_bo(error->active_bo,
-                                         error->active_bo_count,
+       if (active_bo)
+               error->active_bo_count[ndx] =
+                       capture_active_bo(active_bo,
+                                         error->active_bo_count[ndx],
                                          &vm->active_list);
 
-       if (error->pinned_bo)
-               error->pinned_bo_count =
-                       capture_pinned_bo(error->pinned_bo,
-                                         error->pinned_bo_count,
+       if (pinned_bo)
+               error->pinned_bo_count[ndx] =
+                       capture_pinned_bo(pinned_bo,
+                                         error->pinned_bo_count[ndx],
                                          &dev_priv->mm.bound_list);
+       error->active_bo[ndx] = active_bo;
+       error->pinned_bo[ndx] = pinned_bo;
+}
+
+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, i = 0;
+
+       list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+               cnt++;
+
+       if (WARN(cnt > 1, "Multiple VMs not yet supported\n"))
+               cnt = 1;
+
+       vm = &dev_priv->gtt.base;
+
+       error->active_bo = kcalloc(cnt, sizeof(*error->active_bo), GFP_ATOMIC);
+       error->pinned_bo = kcalloc(cnt, sizeof(*error->pinned_bo), GFP_ATOMIC);
+       error->active_bo_count = kcalloc(cnt, sizeof(*error->active_bo_count),
+                                        GFP_ATOMIC);
+       error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count),
+                                        GFP_ATOMIC);
+
+       list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+               i915_gem_capture_vm(dev_priv, error, vm, i++);
 }
 
 /**