1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2019 Intel Corporation
4 */
5
6 #include <linux/string_helpers.h>
7 #include <linux/suspend.h>
8
9 #include "i915_drv.h"
10 #include "i915_irq.h"
11 #include "i915_params.h"
12 #include "intel_context.h"
13 #include "intel_engine_pm.h"
14 #include "intel_gt.h"
15 #include "intel_gt_clock_utils.h"
16 #include "intel_gt_pm.h"
17 #include "intel_gt_print.h"
18 #include "intel_gt_requests.h"
19 #include "intel_llc.h"
20 #include "intel_rc6.h"
21 #include "intel_rps.h"
22 #include "intel_wakeref.h"
23 #include "pxp/intel_pxp_pm.h"
24
25 #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)
26
user_forcewake(struct intel_gt * gt,bool suspend)27 static void user_forcewake(struct intel_gt *gt, bool suspend)
28 {
29 int count = atomic_read(>->user_wakeref);
30
31 /* Inside suspend/resume so single threaded, no races to worry about. */
32 if (likely(!count))
33 return;
34
35 intel_gt_pm_get(gt);
36 if (suspend) {
37 GEM_BUG_ON(count > atomic_read(>->wakeref.count));
38 atomic_sub(count, >->wakeref.count);
39 } else {
40 atomic_add(count, >->wakeref.count);
41 }
42 intel_gt_pm_put(gt);
43 }
44
runtime_begin(struct intel_gt * gt)45 static void runtime_begin(struct intel_gt *gt)
46 {
47 local_irq_disable();
48 #ifdef notyet
49 write_seqcount_begin(>->stats.lock);
50 #else
51 write_seqcount_begin((seqcount_t *)>->stats.lock);
52 #endif
53 gt->stats.start = ktime_get();
54 gt->stats.active = true;
55 #ifdef notyet
56 write_seqcount_end(>->stats.lock);
57 #else
58 write_seqcount_end((seqcount_t *)>->stats.lock);
59 #endif
60 local_irq_enable();
61 }
62
runtime_end(struct intel_gt * gt)63 static void runtime_end(struct intel_gt *gt)
64 {
65 local_irq_disable();
66 #ifdef notyet
67 write_seqcount_begin(>->stats.lock);
68 #else
69 write_seqcount_begin((seqcount_t *)>->stats.lock);
70 #endif
71 gt->stats.active = false;
72 gt->stats.total =
73 ktime_add(gt->stats.total,
74 ktime_sub(ktime_get(), gt->stats.start));
75 #ifdef notyet
76 write_seqcount_end(>->stats.lock);
77 #else
78 write_seqcount_end((seqcount_t *)>->stats.lock);
79 #endif
80 local_irq_enable();
81 }
82
__gt_unpark(struct intel_wakeref * wf)83 static int __gt_unpark(struct intel_wakeref *wf)
84 {
85 struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref);
86 struct drm_i915_private *i915 = gt->i915;
87
88 GT_TRACE(gt, "\n");
89
90 /*
91 * It seems that the DMC likes to transition between the DC states a lot
92 * when there are no connected displays (no active power domains) during
93 * command submission.
94 *
95 * This activity has negative impact on the performance of the chip with
96 * huge latencies observed in the interrupt handler and elsewhere.
97 *
98 * Work around it by grabbing a GT IRQ power domain whilst there is any
99 * GT activity, preventing any DC state transitions.
100 */
101 gt->awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
102 GEM_BUG_ON(!gt->awake);
103
104 intel_rc6_unpark(>->rc6);
105 intel_rps_unpark(>->rps);
106 i915_pmu_gt_unparked(gt);
107 intel_guc_busyness_unpark(gt);
108
109 intel_gt_unpark_requests(gt);
110 runtime_begin(gt);
111
112 return 0;
113 }
114
__gt_park(struct intel_wakeref * wf)115 static int __gt_park(struct intel_wakeref *wf)
116 {
117 struct intel_gt *gt = container_of(wf, typeof(*gt), wakeref);
118 intel_wakeref_t wakeref = fetch_and_zero(>->awake);
119 struct drm_i915_private *i915 = gt->i915;
120
121 GT_TRACE(gt, "\n");
122
123 runtime_end(gt);
124 intel_gt_park_requests(gt);
125
126 intel_guc_busyness_park(gt);
127 i915_vma_parked(gt);
128 i915_pmu_gt_parked(gt);
129 intel_rps_park(>->rps);
130 intel_rc6_park(>->rc6);
131
132 /* Everything switched off, flush any residual interrupt just in case */
133 intel_synchronize_irq(i915);
134
135 /* Defer dropping the display power well for 100ms, it's slow! */
136 GEM_BUG_ON(!wakeref);
137 intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
138
139 return 0;
140 }
141
142 static const struct intel_wakeref_ops wf_ops = {
143 .get = __gt_unpark,
144 .put = __gt_park,
145 };
146
intel_gt_pm_init_early(struct intel_gt * gt)147 void intel_gt_pm_init_early(struct intel_gt *gt)
148 {
149 /*
150 * We access the runtime_pm structure via gt->i915 here rather than
151 * gt->uncore as we do elsewhere in the file because gt->uncore is not
152 * yet initialized for all tiles at this point in the driver startup.
153 * runtime_pm is per-device rather than per-tile, so this is still the
154 * correct structure.
155 */
156 intel_wakeref_init(>->wakeref, gt->i915, &wf_ops);
157 seqcount_mutex_init(>->stats.lock, >->wakeref.mutex);
158 }
159
intel_gt_pm_init(struct intel_gt * gt)160 void intel_gt_pm_init(struct intel_gt *gt)
161 {
162 /*
163 * Enabling power-management should be "self-healing". If we cannot
164 * enable a feature, simply leave it disabled with a notice to the
165 * user.
166 */
167 intel_rc6_init(>->rc6);
168 intel_rps_init(>->rps);
169 }
170
reset_engines(struct intel_gt * gt)171 static bool reset_engines(struct intel_gt *gt)
172 {
173 if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
174 return false;
175
176 return __intel_gt_reset(gt, ALL_ENGINES) == 0;
177 }
178
gt_sanitize(struct intel_gt * gt,bool force)179 static void gt_sanitize(struct intel_gt *gt, bool force)
180 {
181 struct intel_engine_cs *engine;
182 enum intel_engine_id id;
183 intel_wakeref_t wakeref;
184
185 GT_TRACE(gt, "force:%s", str_yes_no(force));
186
187 /* Use a raw wakeref to avoid calling intel_display_power_get early */
188 wakeref = intel_runtime_pm_get(gt->uncore->rpm);
189 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
190
191 intel_gt_check_clock_frequency(gt);
192
193 /*
194 * As we have just resumed the machine and woken the device up from
195 * deep PCI sleep (presumably D3_cold), assume the HW has been reset
196 * back to defaults, recovering from whatever wedged state we left it
197 * in and so worth trying to use the device once more.
198 */
199 if (intel_gt_is_wedged(gt))
200 intel_gt_unset_wedged(gt);
201
202 /* For GuC mode, ensure submission is disabled before stopping ring */
203 intel_uc_reset_prepare(>->uc);
204
205 for_each_engine(engine, gt, id) {
206 if (engine->reset.prepare)
207 engine->reset.prepare(engine);
208
209 if (engine->sanitize)
210 engine->sanitize(engine);
211 }
212
213 if (reset_engines(gt) || force) {
214 for_each_engine(engine, gt, id)
215 __intel_engine_reset(engine, false);
216 }
217
218 intel_uc_reset(>->uc, false);
219
220 for_each_engine(engine, gt, id)
221 if (engine->reset.finish)
222 engine->reset.finish(engine);
223
224 intel_rps_sanitize(>->rps);
225
226 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
227 intel_runtime_pm_put(gt->uncore->rpm, wakeref);
228 }
229
intel_gt_pm_fini(struct intel_gt * gt)230 void intel_gt_pm_fini(struct intel_gt *gt)
231 {
232 intel_rc6_fini(>->rc6);
233 }
234
intel_gt_resume(struct intel_gt * gt)235 int intel_gt_resume(struct intel_gt *gt)
236 {
237 struct intel_engine_cs *engine;
238 enum intel_engine_id id;
239 int err;
240
241 err = intel_gt_has_unrecoverable_error(gt);
242 if (err)
243 return err;
244
245 GT_TRACE(gt, "\n");
246
247 /*
248 * After resume, we may need to poke into the pinned kernel
249 * contexts to paper over any damage caused by the sudden suspend.
250 * Only the kernel contexts should remain pinned over suspend,
251 * allowing us to fixup the user contexts on their first pin.
252 */
253 gt_sanitize(gt, true);
254
255 intel_gt_pm_get(gt);
256
257 intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
258 intel_rc6_sanitize(>->rc6);
259 if (intel_gt_is_wedged(gt)) {
260 err = -EIO;
261 goto out_fw;
262 }
263
264 /* Only when the HW is re-initialised, can we replay the requests */
265 err = intel_gt_init_hw(gt);
266 if (err) {
267 gt_probe_error(gt, "Failed to initialize GPU, declaring it wedged!\n");
268 goto err_wedged;
269 }
270
271 intel_uc_reset_finish(>->uc);
272
273 intel_rps_enable(>->rps);
274 intel_llc_enable(>->llc);
275
276 for_each_engine(engine, gt, id) {
277 intel_engine_pm_get(engine);
278
279 engine->serial++; /* kernel context lost */
280 err = intel_engine_resume(engine);
281
282 intel_engine_pm_put(engine);
283 if (err) {
284 gt_err(gt, "Failed to restart %s (%d)\n",
285 engine->name, err);
286 goto err_wedged;
287 }
288 }
289
290 intel_rc6_enable(>->rc6);
291
292 intel_uc_resume(>->uc);
293
294 user_forcewake(gt, false);
295
296 out_fw:
297 intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
298 intel_gt_pm_put(gt);
299 intel_gt_bind_context_set_ready(gt);
300 return err;
301
302 err_wedged:
303 intel_gt_set_wedged(gt);
304 goto out_fw;
305 }
306
wait_for_suspend(struct intel_gt * gt)307 static void wait_for_suspend(struct intel_gt *gt)
308 {
309 if (!intel_gt_pm_is_awake(gt))
310 return;
311
312 if (intel_gt_wait_for_idle(gt, I915_GT_SUSPEND_IDLE_TIMEOUT) == -ETIME) {
313 /*
314 * Forcibly cancel outstanding work and leave
315 * the gpu quiet.
316 */
317 intel_gt_set_wedged(gt);
318 intel_gt_retire_requests(gt);
319 }
320
321 intel_gt_pm_wait_for_idle(gt);
322 }
323
intel_gt_suspend_prepare(struct intel_gt * gt)324 void intel_gt_suspend_prepare(struct intel_gt *gt)
325 {
326 intel_gt_bind_context_set_unready(gt);
327 user_forcewake(gt, true);
328 wait_for_suspend(gt);
329 }
330
pm_suspend_target(void)331 static suspend_state_t pm_suspend_target(void)
332 {
333 #if IS_ENABLED(CONFIG_SUSPEND) && IS_ENABLED(CONFIG_PM_SLEEP)
334 return pm_suspend_target_state;
335 #else
336 return PM_SUSPEND_TO_IDLE;
337 #endif
338 }
339
intel_gt_suspend_late(struct intel_gt * gt)340 void intel_gt_suspend_late(struct intel_gt *gt)
341 {
342 intel_wakeref_t wakeref;
343
344 /* We expect to be idle already; but also want to be independent */
345 wait_for_suspend(gt);
346
347 if (is_mock_gt(gt))
348 return;
349
350 GEM_BUG_ON(gt->awake);
351
352 intel_uc_suspend(>->uc);
353
354 /*
355 * On disabling the device, we want to turn off HW access to memory
356 * that we no longer own.
357 *
358 * However, not all suspend-states disable the device. S0 (s2idle)
359 * is effectively runtime-suspend, the device is left powered on
360 * but needs to be put into a low power state. We need to keep
361 * powermanagement enabled, but we also retain system state and so
362 * it remains safe to keep on using our allocated memory.
363 */
364 if (pm_suspend_target() == PM_SUSPEND_TO_IDLE)
365 return;
366
367 with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
368 intel_rps_disable(>->rps);
369 intel_rc6_disable(>->rc6);
370 intel_llc_disable(>->llc);
371 }
372
373 gt_sanitize(gt, false);
374
375 GT_TRACE(gt, "\n");
376 }
377
intel_gt_runtime_suspend(struct intel_gt * gt)378 void intel_gt_runtime_suspend(struct intel_gt *gt)
379 {
380 intel_gt_bind_context_set_unready(gt);
381 intel_uc_runtime_suspend(>->uc);
382
383 GT_TRACE(gt, "\n");
384 }
385
intel_gt_runtime_resume(struct intel_gt * gt)386 int intel_gt_runtime_resume(struct intel_gt *gt)
387 {
388 int ret;
389
390 GT_TRACE(gt, "\n");
391 intel_gt_init_swizzling(gt);
392 intel_ggtt_restore_fences(gt->ggtt);
393
394 ret = intel_uc_runtime_resume(>->uc);
395 if (ret)
396 return ret;
397
398 intel_gt_bind_context_set_ready(gt);
399 return 0;
400 }
401
__intel_gt_get_awake_time(const struct intel_gt * gt)402 static ktime_t __intel_gt_get_awake_time(const struct intel_gt *gt)
403 {
404 ktime_t total = gt->stats.total;
405
406 if (gt->stats.active)
407 total = ktime_add(total,
408 ktime_sub(ktime_get(), gt->stats.start));
409
410 return total;
411 }
412
intel_gt_get_awake_time(const struct intel_gt * gt)413 ktime_t intel_gt_get_awake_time(const struct intel_gt *gt)
414 {
415 unsigned int seq;
416 ktime_t total;
417
418 #ifdef notyet
419 do {
420 seq = read_seqcount_begin(>->stats.lock);
421 total = __intel_gt_get_awake_time(gt);
422 } while (read_seqcount_retry(>->stats.lock, seq));
423 #else
424 do {
425 seq = read_seqcount_begin((seqcount_t *)>->stats.lock);
426 total = __intel_gt_get_awake_time(gt);
427 } while (read_seqcount_retry((seqcount_t *)>->stats.lock, seq));
428 #endif
429
430 return total;
431 }
432
433 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
434 #include "selftest_gt_pm.c"
435 #endif
436