diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_reset.c')
-rw-r--r-- | drivers/gpu/drm/i915/gt/intel_reset.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 4c478b38e420..3f907701ef4d 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c | |||
@@ -687,7 +687,6 @@ static void reset_prepare_engine(struct intel_engine_cs *engine) | |||
687 | * written to the powercontext is undefined and so we may lose | 687 | * written to the powercontext is undefined and so we may lose |
688 | * GPU state upon resume, i.e. fail to restart after a reset. | 688 | * GPU state upon resume, i.e. fail to restart after a reset. |
689 | */ | 689 | */ |
690 | intel_engine_pm_get(engine); | ||
691 | intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); | 690 | intel_uncore_forcewake_get(engine->uncore, FORCEWAKE_ALL); |
692 | engine->reset.prepare(engine); | 691 | engine->reset.prepare(engine); |
693 | } | 692 | } |
@@ -718,16 +717,21 @@ static void revoke_mmaps(struct drm_i915_private *i915) | |||
718 | } | 717 | } |
719 | } | 718 | } |
720 | 719 | ||
721 | static void reset_prepare(struct drm_i915_private *i915) | 720 | static intel_engine_mask_t reset_prepare(struct drm_i915_private *i915) |
722 | { | 721 | { |
723 | struct intel_engine_cs *engine; | 722 | struct intel_engine_cs *engine; |
723 | intel_engine_mask_t awake = 0; | ||
724 | enum intel_engine_id id; | 724 | enum intel_engine_id id; |
725 | 725 | ||
726 | intel_gt_pm_get(i915); | 726 | for_each_engine(engine, i915, id) { |
727 | for_each_engine(engine, i915, id) | 727 | if (intel_engine_pm_get_if_awake(engine)) |
728 | awake |= engine->mask; | ||
728 | reset_prepare_engine(engine); | 729 | reset_prepare_engine(engine); |
730 | } | ||
729 | 731 | ||
730 | intel_uc_reset_prepare(i915); | 732 | intel_uc_reset_prepare(i915); |
733 | |||
734 | return awake; | ||
731 | } | 735 | } |
732 | 736 | ||
733 | static void gt_revoke(struct drm_i915_private *i915) | 737 | static void gt_revoke(struct drm_i915_private *i915) |
@@ -761,20 +765,22 @@ static int gt_reset(struct drm_i915_private *i915, | |||
761 | static void reset_finish_engine(struct intel_engine_cs *engine) | 765 | static void reset_finish_engine(struct intel_engine_cs *engine) |
762 | { | 766 | { |
763 | engine->reset.finish(engine); | 767 | engine->reset.finish(engine); |
764 | intel_engine_pm_put(engine); | ||
765 | intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); | 768 | intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); |
769 | |||
770 | intel_engine_signal_breadcrumbs(engine); | ||
766 | } | 771 | } |
767 | 772 | ||
768 | static void reset_finish(struct drm_i915_private *i915) | 773 | static void reset_finish(struct drm_i915_private *i915, |
774 | intel_engine_mask_t awake) | ||
769 | { | 775 | { |
770 | struct intel_engine_cs *engine; | 776 | struct intel_engine_cs *engine; |
771 | enum intel_engine_id id; | 777 | enum intel_engine_id id; |
772 | 778 | ||
773 | for_each_engine(engine, i915, id) { | 779 | for_each_engine(engine, i915, id) { |
774 | reset_finish_engine(engine); | 780 | reset_finish_engine(engine); |
775 | intel_engine_signal_breadcrumbs(engine); | 781 | if (awake & engine->mask) |
782 | intel_engine_pm_put(engine); | ||
776 | } | 783 | } |
777 | intel_gt_pm_put(i915); | ||
778 | } | 784 | } |
779 | 785 | ||
780 | static void nop_submit_request(struct i915_request *request) | 786 | static void nop_submit_request(struct i915_request *request) |
@@ -798,6 +804,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915) | |||
798 | { | 804 | { |
799 | struct i915_gpu_error *error = &i915->gpu_error; | 805 | struct i915_gpu_error *error = &i915->gpu_error; |
800 | struct intel_engine_cs *engine; | 806 | struct intel_engine_cs *engine; |
807 | intel_engine_mask_t awake; | ||
801 | enum intel_engine_id id; | 808 | enum intel_engine_id id; |
802 | 809 | ||
803 | if (test_bit(I915_WEDGED, &error->flags)) | 810 | if (test_bit(I915_WEDGED, &error->flags)) |
@@ -817,7 +824,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915) | |||
817 | * rolling the global seqno forward (since this would complete requests | 824 | * rolling the global seqno forward (since this would complete requests |
818 | * for which we haven't set the fence error to EIO yet). | 825 | * for which we haven't set the fence error to EIO yet). |
819 | */ | 826 | */ |
820 | reset_prepare(i915); | 827 | awake = reset_prepare(i915); |
821 | 828 | ||
822 | /* Even if the GPU reset fails, it should still stop the engines */ | 829 | /* Even if the GPU reset fails, it should still stop the engines */ |
823 | if (!INTEL_INFO(i915)->gpu_reset_clobbers_display) | 830 | if (!INTEL_INFO(i915)->gpu_reset_clobbers_display) |
@@ -841,7 +848,7 @@ static void __i915_gem_set_wedged(struct drm_i915_private *i915) | |||
841 | for_each_engine(engine, i915, id) | 848 | for_each_engine(engine, i915, id) |
842 | engine->cancel_requests(engine); | 849 | engine->cancel_requests(engine); |
843 | 850 | ||
844 | reset_finish(i915); | 851 | reset_finish(i915, awake); |
845 | 852 | ||
846 | GEM_TRACE("end\n"); | 853 | GEM_TRACE("end\n"); |
847 | } | 854 | } |
@@ -951,6 +958,21 @@ static int do_reset(struct drm_i915_private *i915, | |||
951 | return gt_reset(i915, stalled_mask); | 958 | return gt_reset(i915, stalled_mask); |
952 | } | 959 | } |
953 | 960 | ||
961 | static int resume(struct drm_i915_private *i915) | ||
962 | { | ||
963 | struct intel_engine_cs *engine; | ||
964 | enum intel_engine_id id; | ||
965 | int ret; | ||
966 | |||
967 | for_each_engine(engine, i915, id) { | ||
968 | ret = engine->resume(engine); | ||
969 | if (ret) | ||
970 | return ret; | ||
971 | } | ||
972 | |||
973 | return 0; | ||
974 | } | ||
975 | |||
954 | /** | 976 | /** |
955 | * i915_reset - reset chip after a hang | 977 | * i915_reset - reset chip after a hang |
956 | * @i915: #drm_i915_private to reset | 978 | * @i915: #drm_i915_private to reset |
@@ -973,6 +995,7 @@ void i915_reset(struct drm_i915_private *i915, | |||
973 | const char *reason) | 995 | const char *reason) |
974 | { | 996 | { |
975 | struct i915_gpu_error *error = &i915->gpu_error; | 997 | struct i915_gpu_error *error = &i915->gpu_error; |
998 | intel_engine_mask_t awake; | ||
976 | int ret; | 999 | int ret; |
977 | 1000 | ||
978 | GEM_TRACE("flags=%lx\n", error->flags); | 1001 | GEM_TRACE("flags=%lx\n", error->flags); |
@@ -989,7 +1012,7 @@ void i915_reset(struct drm_i915_private *i915, | |||
989 | dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason); | 1012 | dev_notice(i915->drm.dev, "Resetting chip for %s\n", reason); |
990 | error->reset_count++; | 1013 | error->reset_count++; |
991 | 1014 | ||
992 | reset_prepare(i915); | 1015 | awake = reset_prepare(i915); |
993 | 1016 | ||
994 | if (!intel_has_gpu_reset(i915)) { | 1017 | if (!intel_has_gpu_reset(i915)) { |
995 | if (i915_modparams.reset) | 1018 | if (i915_modparams.reset) |
@@ -1024,13 +1047,17 @@ void i915_reset(struct drm_i915_private *i915, | |||
1024 | if (ret) { | 1047 | if (ret) { |
1025 | DRM_ERROR("Failed to initialise HW following reset (%d)\n", | 1048 | DRM_ERROR("Failed to initialise HW following reset (%d)\n", |
1026 | ret); | 1049 | ret); |
1027 | goto error; | 1050 | goto taint; |
1028 | } | 1051 | } |
1029 | 1052 | ||
1053 | ret = resume(i915); | ||
1054 | if (ret) | ||
1055 | goto taint; | ||
1056 | |||
1030 | i915_queue_hangcheck(i915); | 1057 | i915_queue_hangcheck(i915); |
1031 | 1058 | ||
1032 | finish: | 1059 | finish: |
1033 | reset_finish(i915); | 1060 | reset_finish(i915, awake); |
1034 | unlock: | 1061 | unlock: |
1035 | mutex_unlock(&error->wedge_mutex); | 1062 | mutex_unlock(&error->wedge_mutex); |
1036 | return; | 1063 | return; |
@@ -1081,7 +1108,7 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg) | |||
1081 | GEM_TRACE("%s flags=%lx\n", engine->name, error->flags); | 1108 | GEM_TRACE("%s flags=%lx\n", engine->name, error->flags); |
1082 | GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); | 1109 | GEM_BUG_ON(!test_bit(I915_RESET_ENGINE + engine->id, &error->flags)); |
1083 | 1110 | ||
1084 | if (!intel_wakeref_active(&engine->wakeref)) | 1111 | if (!intel_engine_pm_get_if_awake(engine)) |
1085 | return 0; | 1112 | return 0; |
1086 | 1113 | ||
1087 | reset_prepare_engine(engine); | 1114 | reset_prepare_engine(engine); |
@@ -1116,12 +1143,11 @@ int i915_reset_engine(struct intel_engine_cs *engine, const char *msg) | |||
1116 | * process to program RING_MODE, HWSP and re-enable submission. | 1143 | * process to program RING_MODE, HWSP and re-enable submission. |
1117 | */ | 1144 | */ |
1118 | ret = engine->resume(engine); | 1145 | ret = engine->resume(engine); |
1119 | if (ret) | ||
1120 | goto out; | ||
1121 | 1146 | ||
1122 | out: | 1147 | out: |
1123 | intel_engine_cancel_stop_cs(engine); | 1148 | intel_engine_cancel_stop_cs(engine); |
1124 | reset_finish_engine(engine); | 1149 | reset_finish_engine(engine); |
1150 | intel_engine_pm_put(engine); | ||
1125 | return ret; | 1151 | return ret; |
1126 | } | 1152 | } |
1127 | 1153 | ||