drm/i915: Reduce GPU error capture mutex hold time
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 16 Sep 2020 09:00:59 +0000 (10:00 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 18 Sep 2020 10:53:04 +0000 (11:53 +0100)
Shrink the hold time for the error capture mutex to just around the
acquire/release of the PTE used for reading back the object via the
Global GTT. For platforms that do not need the GGTT read back, we can
skip the mutex entirely and allow concurrent error capture. Where we do
use the GGTT, by restricting the hold time around the slow readback and
compression, we are more resilient against softlockups (khungtaskd) as
the heartbeat may well also trigger an error while the first is on
going, and this allows the heartbeat reset to skip past the capture and
not be stalled.

Testcase: igt/gem_exec_capture/many-*
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200916090059.3189-3-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_gpu_error.c

index 6551ff04d5a6c4aa366301d4bce2176d539337da..41a82855d046d05b6772c33be448a70f73d1e5b5 100644 (file)
@@ -1026,6 +1026,7 @@ i915_vma_coredump_create(const struct intel_gt *gt,
                dma_addr_t dma;
 
                for_each_sgt_daddr(dma, iter, vma->pages) {
+                       mutex_lock(&ggtt->error_mutex);
                        ggtt->vm.insert_page(&ggtt->vm, dma, slot,
                                             I915_CACHE_NONE, 0);
                        mb();
@@ -1035,6 +1036,10 @@ i915_vma_coredump_create(const struct intel_gt *gt,
                                            (void  __force *)s, dst,
                                            true);
                        io_mapping_unmap(s);
+
+                       mb();
+                       ggtt->vm.clear_range(&ggtt->vm, slot, PAGE_SIZE);
+                       mutex_unlock(&ggtt->error_mutex);
                        if (ret)
                                break;
                }
@@ -1506,25 +1511,6 @@ gt_record_uc(struct intel_gt_coredump *gt,
        return error_uc;
 }
 
-static void gt_capture_prepare(struct intel_gt_coredump *gt)
-{
-       struct i915_ggtt *ggtt = gt->_gt->ggtt;
-
-       mutex_lock(&ggtt->error_mutex);
-}
-
-static void gt_capture_finish(struct intel_gt_coredump *gt)
-{
-       struct i915_ggtt *ggtt = gt->_gt->ggtt;
-
-       if (drm_mm_node_allocated(&ggtt->error_capture))
-               ggtt->vm.clear_range(&ggtt->vm,
-                                    ggtt->error_capture.start,
-                                    PAGE_SIZE);
-
-       mutex_unlock(&ggtt->error_mutex);
-}
-
 /* Capture all registers which don't fit into another category. */
 static void gt_record_regs(struct intel_gt_coredump *gt)
 {
@@ -1783,8 +1769,6 @@ i915_vma_capture_prepare(struct intel_gt_coredump *gt)
                return NULL;
        }
 
-       gt_capture_prepare(gt);
-
        return compress;
 }
 
@@ -1794,8 +1778,6 @@ void i915_vma_capture_finish(struct intel_gt_coredump *gt,
        if (!compress)
                return;
 
-       gt_capture_finish(gt);
-
        compress_fini(compress);
        kfree(compress);
 }