0001
0002
0003
0004
0005
0006 #include <linux/string_helpers.h>
0007 #include <linux/suspend.h>
0008
0009 #include "i915_drv.h"
0010 #include "i915_params.h"
0011 #include "intel_context.h"
0012 #include "intel_engine_pm.h"
0013 #include "intel_gt.h"
0014 #include "intel_gt_clock_utils.h"
0015 #include "intel_gt_pm.h"
0016 #include "intel_gt_requests.h"
0017 #include "intel_llc.h"
0018 #include "intel_pm.h"
0019 #include "intel_rc6.h"
0020 #include "intel_rps.h"
0021 #include "intel_wakeref.h"
0022 #include "pxp/intel_pxp_pm.h"
0023
0024 #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)
0025
0026 static void user_forcewake(struct intel_gt *gt, bool suspend)
0027 {
0028 int count = atomic_read(>->user_wakeref);
0029
0030
0031 if (likely(!count))
0032 return;
0033
0034 intel_gt_pm_get(gt);
0035 if (suspend) {
0036 GEM_BUG_ON(count > atomic_read(>->wakeref.count));
0037 atomic_sub(count, >->wakeref.count);
0038 } else {
0039 atomic_add(count, >->wakeref.count);
0040 }
0041 intel_gt_pm_put(gt);
0042 }
0043
0044 static void runtime_begin(struct intel_gt *gt)
0045 {
0046 local_irq_disable();
0047 write_seqcount_begin(>->stats.lock);
0048 gt->stats.start = ktime_get();
0049 gt->stats.active = true;
0050 write_seqcount_end(>->stats.lock);
0051 local_irq_enable();
0052 }
0053
0054 static void runtime_end(struct intel_gt *gt)
0055 {
0056 local_irq_disable();
0057 write_seqcount_begin(>->stats.lock);
0058 gt->stats.active = false;
0059 gt->stats.total =
0060 ktime_add(gt->stats.total,
0061 ktime_sub(ktime_get(), gt->stats.start));
0062 write_seqcount_end(>->stats.lock);
0063 local_irq_enable();
0064 }
0065
0066 static int __gt_unpark(struct intel_wakeref *wf)
0067 {
0068 struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref);
0069 struct drm_i915_private *i915 = gt->i915;
0070
0071 GT_TRACE(gt, "\n");
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
0085 GEM_BUG_ON(!gt->awake);
0086
0087 intel_rc6_unpark(>->rc6);
0088 intel_rps_unpark(>->rps);
0089 i915_pmu_gt_unparked(i915);
0090 intel_guc_busyness_unpark(gt);
0091
0092 intel_gt_unpark_requests(gt);
0093 runtime_begin(gt);
0094
0095 return 0;
0096 }
0097
0098 static int __gt_park(struct intel_wakeref *wf)
0099 {
0100 struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref);
0101 intel_wakeref_t wakeref = fetch_and_zero(>->awake);
0102 struct drm_i915_private *i915 = gt->i915;
0103
0104 GT_TRACE(gt, "\n");
0105
0106 runtime_end(gt);
0107 intel_gt_park_requests(gt);
0108
0109 intel_guc_busyness_park(gt);
0110 i915_vma_parked(gt);
0111 i915_pmu_gt_parked(i915);
0112 intel_rps_park(>->rps);
0113 intel_rc6_park(>->rc6);
0114
0115
0116 intel_synchronize_irq(i915);
0117
0118
0119 GEM_BUG_ON(!wakeref);
0120 intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
0121
0122 return 0;
0123 }
0124
0125 static const struct intel_wakeref_ops wf_ops = {
0126 .get = __gt_unpark,
0127 .put = __gt_park,
0128 };
0129
0130 void intel_gt_pm_init_early(struct intel_gt *gt)
0131 {
0132
0133
0134
0135
0136
0137
0138
0139 intel_wakeref_init(>->wakeref, >->i915->runtime_pm, &wf_ops);
0140 seqcount_mutex_init(>->stats.lock, >->wakeref.mutex);
0141 }
0142
0143 void intel_gt_pm_init(struct intel_gt *gt)
0144 {
0145
0146
0147
0148
0149
0150 intel_rc6_init(>->rc6);
0151 intel_rps_init(>->rps);
0152 }
0153
0154 static bool reset_engines(struct intel_gt *gt)
0155 {
0156 if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
0157 return false;
0158
0159 return __intel_gt_reset(gt, ALL_ENGINES) == 0;
0160 }
0161
0162 static void gt_sanitize(struct intel_gt *gt, bool force)
0163 {
0164 struct intel_engine_cs *engine;
0165 enum intel_engine_id id;
0166 intel_wakeref_t wakeref;
0167
0168 GT_TRACE(gt, "force:%s", str_yes_no(force));
0169
0170
0171 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
0172 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
0173
0174 intel_gt_check_clock_frequency(gt);
0175
0176
0177
0178
0179
0180
0181
0182 if (intel_gt_is_wedged(gt))
0183 intel_gt_unset_wedged(gt);
0184
0185
0186 intel_uc_reset_prepare(>->uc);
0187
0188 for_each_engine(engine, gt, id) {
0189 if (engine->reset.prepare)
0190 engine->reset.prepare(engine);
0191
0192 if (engine->sanitize)
0193 engine->sanitize(engine);
0194 }
0195
0196 if (reset_engines(gt) || force) {
0197 for_each_engine(engine, gt, id)
0198 __intel_engine_reset(engine, false);
0199 }
0200
0201 intel_uc_reset(>->uc, false);
0202
0203 for_each_engine(engine, gt, id)
0204 if (engine->reset.finish)
0205 engine->reset.finish(engine);
0206
0207 intel_rps_sanitize(>->rps);
0208
0209 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
0210 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
0211 }
0212
0213 void intel_gt_pm_fini(struct intel_gt *gt)
0214 {
0215 intel_rc6_fini(>->rc6);
0216 }
0217
0218 int intel_gt_resume(struct intel_gt *gt)
0219 {
0220 struct intel_engine_cs *engine;
0221 enum intel_engine_id id;
0222 int err;
0223
0224 err = intel_gt_has_unrecoverable_error(gt);
0225 if (err)
0226 return err;
0227
0228 GT_TRACE(gt, "\n");
0229
0230
0231
0232
0233
0234
0235
0236 gt_sanitize(gt, true);
0237
0238 intel_gt_pm_get(gt);
0239
0240 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
0241 intel_rc6_sanitize(>->rc6);
0242 if (intel_gt_is_wedged(gt)) {
0243 err = -EIO;
0244 goto out_fw;
0245 }
0246
0247
0248 err = intel_gt_init_hw(gt);
0249 if (err) {
0250 i915_probe_error(gt->i915,
0251 "Failed to initialize GPU, declaring it wedged!\n");
0252 goto err_wedged;
0253 }
0254
0255 intel_uc_reset_finish(>->uc);
0256
0257 intel_rps_enable(>->rps);
0258 intel_llc_enable(>->llc);
0259
0260 for_each_engine(engine, gt, id) {
0261 intel_engine_pm_get(engine);
0262
0263 engine->serial++;
0264 err = intel_engine_resume(engine);
0265
0266 intel_engine_pm_put(engine);
0267 if (err) {
0268 drm_err(>->i915->drm,
0269 "Failed to restart %s (%d)\n",
0270 engine->name, err);
0271 goto err_wedged;
0272 }
0273 }
0274
0275 intel_rc6_enable(>->rc6);
0276
0277 intel_uc_resume(>->uc);
0278
0279 intel_pxp_resume(>->pxp);
0280
0281 user_forcewake(gt, false);
0282
0283 out_fw:
0284 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
0285 intel_gt_pm_put(gt);
0286 return err;
0287
0288 err_wedged:
0289 intel_gt_set_wedged(gt);
0290 goto out_fw;
0291 }
0292
0293 static void wait_for_suspend(struct intel_gt *gt)
0294 {
0295 if (!intel_gt_pm_is_awake(gt))
0296 return;
0297
0298 if (intel_gt_wait_for_idle(gt, I915_GT_SUSPEND_IDLE_TIMEOUT) == -ETIME) {
0299
0300
0301
0302
0303 intel_gt_set_wedged(gt);
0304 intel_gt_retire_requests(gt);
0305 }
0306
0307 intel_gt_pm_wait_for_idle(gt);
0308 }
0309
0310 void intel_gt_suspend_prepare(struct intel_gt *gt)
0311 {
0312 user_forcewake(gt, true);
0313 wait_for_suspend(gt);
0314
0315 intel_pxp_suspend_prepare(>->pxp);
0316 }
0317
0318 static suspend_state_t pm_suspend_target(void)
0319 {
0320 #if IS_ENABLED(CONFIG_SUSPEND) && IS_ENABLED(CONFIG_PM_SLEEP)
0321 return pm_suspend_target_state;
0322 #else
0323 return PM_SUSPEND_TO_IDLE;
0324 #endif
0325 }
0326
0327 void intel_gt_suspend_late(struct intel_gt *gt)
0328 {
0329 intel_wakeref_t wakeref;
0330
0331
0332 wait_for_suspend(gt);
0333
0334 if (is_mock_gt(gt))
0335 return;
0336
0337 GEM_BUG_ON(gt->awake);
0338
0339 intel_uc_suspend(>->uc);
0340 intel_pxp_suspend(>->pxp);
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 if (pm_suspend_target() == PM_SUSPEND_TO_IDLE)
0353 return;
0354
0355 with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
0356 intel_rps_disable(>->rps);
0357 intel_rc6_disable(>->rc6);
0358 intel_llc_disable(>->llc);
0359 }
0360
0361 gt_sanitize(gt, false);
0362
0363 GT_TRACE(gt, "\n");
0364 }
0365
0366 void intel_gt_runtime_suspend(struct intel_gt *gt)
0367 {
0368 intel_pxp_runtime_suspend(>->pxp);
0369 intel_uc_runtime_suspend(>->uc);
0370
0371 GT_TRACE(gt, "\n");
0372 }
0373
0374 int intel_gt_runtime_resume(struct intel_gt *gt)
0375 {
0376 int ret;
0377
0378 GT_TRACE(gt, "\n");
0379 intel_gt_init_swizzling(gt);
0380 intel_ggtt_restore_fences(gt->ggtt);
0381
0382 ret = intel_uc_runtime_resume(>->uc);
0383 if (ret)
0384 return ret;
0385
0386 intel_pxp_runtime_resume(>->pxp);
0387
0388 return 0;
0389 }
0390
0391 static ktime_t __intel_gt_get_awake_time(const struct intel_gt *gt)
0392 {
0393 ktime_t total = gt->stats.total;
0394
0395 if (gt->stats.active)
0396 total = ktime_add(total,
0397 ktime_sub(ktime_get(), gt->stats.start));
0398
0399 return total;
0400 }
0401
0402 ktime_t intel_gt_get_awake_time(const struct intel_gt *gt)
0403 {
0404 unsigned int seq;
0405 ktime_t total;
0406
0407 do {
0408 seq = read_seqcount_begin(>->stats.lock);
0409 total = __intel_gt_get_awake_time(gt);
0410 } while (read_seqcount_retry(>->stats.lock, seq));
0411
0412 return total;
0413 }
0414
0415 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
0416 #include "selftest_gt_pm.c"
0417 #endif