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