aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2019-03-08 04:36:56 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2019-03-08 05:57:08 -0500
commitc6eeb4797eb94ad14bb34adfccbc6addad2cfd48 (patch)
treeec32a5bc5b8c8e3ce3abfb529eb0b5b8365e4ab7
parent604c37d76689d6a0e5492f5ff71886ab83817208 (diff)
drm/i915: Reduce presumption of request ordering for barriers
Currently we assume that we know the order in which requests run and so can determine if we need to reissue a switch-to-kernel-context prior to idling. That assumption does not hold for the future, so instead of tracking which barriers have been used, simply determine if we have ever switched away from the kernel context by using the engine and before idling ensure that all engines that have been used since the last idle are synchronously switched back to the kernel context for safety (and else of shrinking memory while idle). v2: Use intel_engine_mask_t and ALL_ENGINES Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190308093657.8640-3-chris@chris-wilson.co.uk
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c12
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c66
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_evict.c2
-rw-r--r--drivers/gpu/drm/i915/i915_request.c1
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c5
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_context.c3
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_flush_test.c2
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c4
10 files changed, 27 insertions, 72 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b8a5281d8adf..c4ffe19ec698 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1995,6 +1995,7 @@ struct drm_i915_private {
1995 struct list_head hwsp_free_list; 1995 struct list_head hwsp_free_list;
1996 } timelines; 1996 } timelines;
1997 1997
1998 intel_engine_mask_t active_engines;
1998 struct list_head active_rings; 1999 struct list_head active_rings;
1999 struct list_head closed_vma; 2000 struct list_head closed_vma;
2000 u32 active_requests; 2001 u32 active_requests;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 539ee78f6d9a..961237b90b40 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2845,7 +2845,8 @@ static void assert_kernel_context_is_current(struct drm_i915_private *i915)
2845 } 2845 }
2846} 2846}
2847 2847
2848static bool switch_to_kernel_context_sync(struct drm_i915_private *i915) 2848static bool switch_to_kernel_context_sync(struct drm_i915_private *i915,
2849 unsigned long mask)
2849{ 2850{
2850 bool result = true; 2851 bool result = true;
2851 2852
@@ -2854,7 +2855,7 @@ static bool switch_to_kernel_context_sync(struct drm_i915_private *i915)
2854 * to save itself before we report the failure. Yes, this may be a 2855 * to save itself before we report the failure. Yes, this may be a
2855 * false positive due to e.g. ENOMEM, caveat emptor! 2856 * false positive due to e.g. ENOMEM, caveat emptor!
2856 */ 2857 */
2857 if (i915_gem_switch_to_kernel_context(i915)) 2858 if (i915_gem_switch_to_kernel_context(i915, mask))
2858 result = false; 2859 result = false;
2859 2860
2860 if (i915_gem_wait_for_idle(i915, 2861 if (i915_gem_wait_for_idle(i915,
@@ -2879,7 +2880,8 @@ static bool switch_to_kernel_context_sync(struct drm_i915_private *i915)
2879 2880
2880static bool load_power_context(struct drm_i915_private *i915) 2881static bool load_power_context(struct drm_i915_private *i915)
2881{ 2882{
2882 if (!switch_to_kernel_context_sync(i915)) 2883 /* Force loading the kernel context on all engines */
2884 if (!switch_to_kernel_context_sync(i915, ALL_ENGINES))
2883 return false; 2885 return false;
2884 2886
2885 /* 2887 /*
@@ -2927,7 +2929,7 @@ i915_gem_idle_work_handler(struct work_struct *work)
2927 !i915->gt.active_requests) { 2929 !i915->gt.active_requests) {
2928 ++i915->gt.active_requests; /* don't requeue idle */ 2930 ++i915->gt.active_requests; /* don't requeue idle */
2929 2931
2930 switch_to_kernel_context_sync(i915); 2932 switch_to_kernel_context_sync(i915, i915->gt.active_engines);
2931 2933
2932 if (!--i915->gt.active_requests) { 2934 if (!--i915->gt.active_requests) {
2933 __i915_gem_park(i915); 2935 __i915_gem_park(i915);
@@ -4380,7 +4382,7 @@ void i915_gem_suspend(struct drm_i915_private *i915)
4380 * state. Fortunately, the kernel_context is disposable and we do 4382 * state. Fortunately, the kernel_context is disposable and we do
4381 * not rely on its state. 4383 * not rely on its state.
4382 */ 4384 */
4383 switch_to_kernel_context_sync(i915); 4385 switch_to_kernel_context_sync(i915, i915->gt.active_engines);
4384 4386
4385 mutex_unlock(&i915->drm.struct_mutex); 4387 mutex_unlock(&i915->drm.struct_mutex);
4386 i915_reset_flush(i915); 4388 i915_reset_flush(i915);
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 9a3eb4f66d85..486203e9d205 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -704,63 +704,10 @@ last_request_on_engine(struct i915_timeline *timeline,
704 return NULL; 704 return NULL;
705} 705}
706 706
707static bool engine_has_kernel_context_barrier(struct intel_engine_cs *engine) 707int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915,
708{ 708 unsigned long mask)
709 struct drm_i915_private *i915 = engine->i915;
710 const struct intel_context * const ce =
711 to_intel_context(i915->kernel_context, engine);
712 struct i915_timeline *barrier = ce->ring->timeline;
713 struct intel_ring *ring;
714 bool any_active = false;
715
716 lockdep_assert_held(&i915->drm.struct_mutex);
717 list_for_each_entry(ring, &i915->gt.active_rings, active_link) {
718 struct i915_request *rq;
719
720 rq = last_request_on_engine(ring->timeline, engine);
721 if (!rq)
722 continue;
723
724 any_active = true;
725
726 if (rq->hw_context == ce)
727 continue;
728
729 /*
730 * Was this request submitted after the previous
731 * switch-to-kernel-context?
732 */
733 if (!i915_timeline_sync_is_later(barrier, &rq->fence)) {
734 GEM_TRACE("%s needs barrier for %llx:%lld\n",
735 ring->timeline->name,
736 rq->fence.context,
737 rq->fence.seqno);
738 return false;
739 }
740
741 GEM_TRACE("%s has barrier after %llx:%lld\n",
742 ring->timeline->name,
743 rq->fence.context,
744 rq->fence.seqno);
745 }
746
747 /*
748 * If any other timeline was still active and behind the last barrier,
749 * then our last switch-to-kernel-context must still be queued and
750 * will run last (leaving the engine in the kernel context when it
751 * eventually idles).
752 */
753 if (any_active)
754 return true;
755
756 /* The engine is idle; check that it is idling in the kernel context. */
757 return engine->last_retired_context == ce;
758}
759
760int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915)
761{ 709{
762 struct intel_engine_cs *engine; 710 struct intel_engine_cs *engine;
763 enum intel_engine_id id;
764 711
765 GEM_TRACE("awake?=%s\n", yesno(i915->gt.awake)); 712 GEM_TRACE("awake?=%s\n", yesno(i915->gt.awake));
766 713
@@ -771,17 +718,11 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915)
771 if (i915_terminally_wedged(i915)) 718 if (i915_terminally_wedged(i915))
772 return 0; 719 return 0;
773 720
774 i915_retire_requests(i915); 721 for_each_engine_masked(engine, i915, mask, mask) {
775
776 for_each_engine(engine, i915, id) {
777 struct intel_ring *ring; 722 struct intel_ring *ring;
778 struct i915_request *rq; 723 struct i915_request *rq;
779 724
780 GEM_BUG_ON(!to_intel_context(i915->kernel_context, engine)); 725 GEM_BUG_ON(!to_intel_context(i915->kernel_context, engine));
781 if (engine_has_kernel_context_barrier(engine))
782 continue;
783
784 GEM_TRACE("emit barrier on %s\n", engine->name);
785 726
786 rq = i915_request_alloc(engine, i915->kernel_context); 727 rq = i915_request_alloc(engine, i915->kernel_context);
787 if (IS_ERR(rq)) 728 if (IS_ERR(rq))
@@ -805,7 +746,6 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915)
805 i915_sw_fence_await_sw_fence_gfp(&rq->submit, 746 i915_sw_fence_await_sw_fence_gfp(&rq->submit,
806 &prev->submit, 747 &prev->submit,
807 I915_FENCE_GFP); 748 I915_FENCE_GFP);
808 i915_timeline_sync_set(rq->timeline, &prev->fence);
809 } 749 }
810 750
811 i915_request_add(rq); 751 i915_request_add(rq);
diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
index 2f9ef333acaa..e1188d77a23d 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
@@ -372,7 +372,8 @@ int i915_gem_context_open(struct drm_i915_private *i915,
372void i915_gem_context_close(struct drm_file *file); 372void i915_gem_context_close(struct drm_file *file);
373 373
374int i915_switch_context(struct i915_request *rq); 374int i915_switch_context(struct i915_request *rq);
375int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv); 375int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915,
376 unsigned long engine_mask);
376 377
377void i915_gem_context_release(struct kref *ctx_ref); 378void i915_gem_context_release(struct kref *ctx_ref);
378struct i915_gem_context * 379struct i915_gem_context *
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 68d74c50ac39..7d8e90dfca84 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -62,7 +62,7 @@ static int ggtt_flush(struct drm_i915_private *i915)
62 * the hopes that we can then remove contexts and the like only 62 * the hopes that we can then remove contexts and the like only
63 * bound by their active reference. 63 * bound by their active reference.
64 */ 64 */
65 err = i915_gem_switch_to_kernel_context(i915); 65 err = i915_gem_switch_to_kernel_context(i915, i915->gt.active_engines);
66 if (err) 66 if (err)
67 return err; 67 return err;
68 68
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index f8a63495114c..9533a85cb0b3 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -1068,6 +1068,7 @@ void i915_request_add(struct i915_request *request)
1068 GEM_TRACE("marking %s as active\n", ring->timeline->name); 1068 GEM_TRACE("marking %s as active\n", ring->timeline->name);
1069 list_add(&ring->active_link, &request->i915->gt.active_rings); 1069 list_add(&ring->active_link, &request->i915->gt.active_rings);
1070 } 1070 }
1071 request->i915->gt.active_engines |= request->engine->mask;
1071 request->emitted_jiffies = jiffies; 1072 request->emitted_jiffies = jiffies;
1072 1073
1073 /* 1074 /*
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 555a4590fa23..18174f808fd8 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1106,6 +1106,9 @@ bool intel_engine_has_kernel_context(const struct intel_engine_cs *engine)
1106 1106
1107 lockdep_assert_held(&engine->i915->drm.struct_mutex); 1107 lockdep_assert_held(&engine->i915->drm.struct_mutex);
1108 1108
1109 if (!engine->context_size)
1110 return true;
1111
1109 /* 1112 /*
1110 * Check the last context seen by the engine. If active, it will be 1113 * Check the last context seen by the engine. If active, it will be
1111 * the last request that remains in the timeline. When idle, it is 1114 * the last request that remains in the timeline. When idle, it is
@@ -1205,6 +1208,8 @@ void intel_engines_park(struct drm_i915_private *i915)
1205 i915_gem_batch_pool_fini(&engine->batch_pool); 1208 i915_gem_batch_pool_fini(&engine->batch_pool);
1206 engine->execlists.no_priolist = false; 1209 engine->execlists.no_priolist = false;
1207 } 1210 }
1211
1212 i915->gt.active_engines = 0;
1208} 1213}
1209 1214
1210/** 1215/**
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index 755c4a7304b2..5b8614b2fbe4 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -1512,7 +1512,8 @@ static int __igt_switch_to_kernel_context(struct drm_i915_private *i915,
1512 } 1512 }
1513 } 1513 }
1514 1514
1515 err = i915_gem_switch_to_kernel_context(i915); 1515 err = i915_gem_switch_to_kernel_context(i915,
1516 i915->gt.active_engines);
1516 if (err) 1517 if (err)
1517 return err; 1518 return err;
1518 1519
diff --git a/drivers/gpu/drm/i915/selftests/igt_flush_test.c b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
index e0d3122fd35a..94aee4071a66 100644
--- a/drivers/gpu/drm/i915/selftests/igt_flush_test.c
+++ b/drivers/gpu/drm/i915/selftests/igt_flush_test.c
@@ -14,7 +14,7 @@ int igt_flush_test(struct drm_i915_private *i915, unsigned int flags)
14 cond_resched(); 14 cond_resched();
15 15
16 if (flags & I915_WAIT_LOCKED && 16 if (flags & I915_WAIT_LOCKED &&
17 i915_gem_switch_to_kernel_context(i915)) { 17 i915_gem_switch_to_kernel_context(i915, i915->gt.active_engines)) {
18 pr_err("Failed to switch back to kernel context; declaring wedged\n"); 18 pr_err("Failed to switch back to kernel context; declaring wedged\n");
19 i915_gem_set_wedged(i915); 19 i915_gem_set_wedged(i915);
20 } 20 }
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index b2c7808e0595..54cfb611c0aa 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -109,6 +109,10 @@ static void mock_retire_work_handler(struct work_struct *work)
109 109
110static void mock_idle_work_handler(struct work_struct *work) 110static void mock_idle_work_handler(struct work_struct *work)
111{ 111{
112 struct drm_i915_private *i915 =
113 container_of(work, typeof(*i915), gt.idle_work.work);
114
115 i915->gt.active_engines = 0;
112} 116}
113 117
114static int pm_domain_resume(struct device *dev) 118static int pm_domain_resume(struct device *dev)