Skip to content

Commit a70a9e9

Browse files
icklejlahtine-intel
authored andcommitted
drm/i915: Defer rc6 shutdown to suspend_late
Currently we shutdown rc6 during i915_gem_resume() but this is called during the preparation phase (i915_drm_prepare) for all suspend paths, but we only want to shutdown rc6 for S3+. Move the actual shutdown to i915_gem_suspend_late(). We then need to differentiate between suspend targets, to distinguish S0 (s2idle) where the device is kept awake but needs to be in a low power mode (the same as runtime suspend) from the device suspend levels where we lose control of HW and so must disable any HW access to dangling memory. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111909 Fixes: c113236 ("drm/i915: Extract GT render sleep (rc6) management") Testcase: igt/gem_exec_suspend/power-S0 Signed-off-by: Chris Wilson <[email protected]> Cc: Andi Shyti <[email protected]> Acked-by: Andi Shyti <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit c601cb2) Signed-off-by: Joonas Lahtinen <[email protected]>
1 parent d4033a9 commit a70a9e9

File tree

5 files changed

+49
-9
lines changed

5 files changed

+49
-9
lines changed

drivers/gpu/drm/i915/gem/i915_gem_pm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void i915_gem_suspend(struct drm_i915_private *i915)
2727
* state. Fortunately, the kernel_context is disposable and we do
2828
* not rely on its state.
2929
*/
30-
intel_gt_suspend(&i915->gt);
30+
intel_gt_suspend_prepare(&i915->gt);
3131

3232
i915_gem_drain_freed_objects(i915);
3333
}
@@ -69,6 +69,8 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
6969
* machine in an unusable condition.
7070
*/
7171

72+
intel_gt_suspend_late(&i915->gt);
73+
7274
spin_lock_irqsave(&i915->mm.obj_lock, flags);
7375
for (phase = phases; *phase; phase++) {
7476
LIST_HEAD(keep);

drivers/gpu/drm/i915/gt/intel_gt_pm.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* Copyright © 2019 Intel Corporation
55
*/
66

7+
#include <linux/suspend.h>
8+
79
#include "i915_drv.h"
810
#include "i915_globals.h"
911
#include "i915_params.h"
@@ -236,8 +238,11 @@ int intel_gt_resume(struct intel_gt *gt)
236238
return err;
237239
}
238240

239-
static void wait_for_idle(struct intel_gt *gt)
241+
static void wait_for_suspend(struct intel_gt *gt)
240242
{
243+
if (!intel_gt_pm_is_awake(gt))
244+
return;
245+
241246
if (intel_gt_wait_for_idle(gt, I915_GEM_IDLE_TIMEOUT) == -ETIME) {
242247
/*
243248
* Forcibly cancel outstanding work and leave
@@ -246,19 +251,46 @@ static void wait_for_idle(struct intel_gt *gt)
246251
intel_gt_set_wedged(gt);
247252
}
248253

254+
GEM_BUG_ON(atomic_read(&gt->user_wakeref));
249255
intel_gt_pm_wait_for_idle(gt);
250256
}
251257

252-
void intel_gt_suspend(struct intel_gt *gt)
258+
void intel_gt_suspend_prepare(struct intel_gt *gt)
253259
{
254-
intel_wakeref_t wakeref;
255-
256260
user_forcewake(gt, true);
261+
wait_for_suspend(gt);
262+
263+
intel_uc_suspend(&gt->uc);
264+
}
265+
266+
static suspend_state_t pm_suspend_target(void)
267+
{
268+
#if IS_ENABLED(CONFIG_PM_SLEEP)
269+
return pm_suspend_target_state;
270+
#else
271+
return PM_SUSPEND_TO_IDLE;
272+
#endif
273+
}
274+
275+
void intel_gt_suspend_late(struct intel_gt *gt)
276+
{
277+
intel_wakeref_t wakeref;
257278

258279
/* We expect to be idle already; but also want to be independent */
259-
wait_for_idle(gt);
280+
wait_for_suspend(gt);
260281

261-
intel_uc_suspend(&gt->uc);
282+
/*
283+
* On disabling the device, we want to turn off HW access to memory
284+
* that we no longer own.
285+
*
286+
* However, not all suspend-states disable the device. S0 (s2idle)
287+
* is effectively runtime-suspend, the device is left powered on
288+
* but needs to be put into a low power state. We need to keep
289+
* powermanagement enabled, but we also retain system state and so
290+
* it remains safe to keep on using our allocated memory.
291+
*/
292+
if (pm_suspend_target() == PM_SUSPEND_TO_IDLE)
293+
return;
262294

263295
with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
264296
intel_rps_disable(&gt->rps);

drivers/gpu/drm/i915/gt/intel_gt_pm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ void intel_gt_pm_fini(struct intel_gt *gt);
4343

4444
void intel_gt_sanitize(struct intel_gt *gt, bool force);
4545

46+
void intel_gt_suspend_prepare(struct intel_gt *gt);
47+
void intel_gt_suspend_late(struct intel_gt *gt);
4648
int intel_gt_resume(struct intel_gt *gt);
47-
void intel_gt_suspend(struct intel_gt *gt);
4849

4950
void intel_gt_runtime_suspend(struct intel_gt *gt);
5051
int intel_gt_runtime_resume(struct intel_gt *gt);

drivers/gpu/drm/i915/gt/intel_rc6.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,11 @@ void intel_rc6_init(struct intel_rc6 *rc6)
525525

526526
void intel_rc6_sanitize(struct intel_rc6 *rc6)
527527
{
528+
if (rc6->enabled) { /* unbalanced suspend/resume */
529+
rpm_get(rc6);
530+
rc6->enabled = false;
531+
}
532+
528533
if (rc6->supported)
529534
__intel_rc6_disable(rc6);
530535
}

drivers/gpu/drm/i915/gt/selftest_gt_pm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ static int live_gt_resume(void *arg)
1515

1616
/* Do several suspend/resume cycles to check we don't explode! */
1717
do {
18-
intel_gt_suspend(gt);
18+
intel_gt_suspend_late(gt);
1919

2020
if (gt->rc6.enabled) {
2121
pr_err("rc6 still enabled after suspend!\n");

0 commit comments

Comments
 (0)