1 |
From d3de5616d36462a646f5b360ba82d3b09ff668eb Mon Sep 17 00:00:00 2001 |
2 |
From: Chris Wilson <chris@chris-wilson.co.uk> |
3 |
Date: Mon, 12 Dec 2022 17:13:38 +0100 |
4 |
Subject: drm/i915/gt: Reset twice |
5 |
|
6 |
From: Chris Wilson <chris@chris-wilson.co.uk> |
7 |
|
8 |
commit d3de5616d36462a646f5b360ba82d3b09ff668eb upstream. |
9 |
|
10 |
After applying an engine reset, on some platforms like Jasperlake, we |
11 |
occasionally detect that the engine state is not cleared until shortly |
12 |
after the resume. As we try to resume the engine with volatile internal |
13 |
state, the first request fails with a spurious CS event (it looks like |
14 |
it reports a lite-restore to the hung context, instead of the expected |
15 |
idle->active context switch). |
16 |
|
17 |
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> |
18 |
Cc: stable@vger.kernel.org |
19 |
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> |
20 |
Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com> |
21 |
Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com> |
22 |
Link: https://patchwork.freedesktop.org/patch/msgid/20221212161338.1007659-1-andi.shyti@linux.intel.com |
23 |
(cherry picked from commit 3db9d590557da3aa2c952f2fecd3e9b703dad790) |
24 |
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> |
25 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
26 |
--- |
27 |
drivers/gpu/drm/i915/gt/intel_reset.c | 34 ++++++++++++++++++++++++++++------ |
28 |
1 file changed, 28 insertions(+), 6 deletions(-) |
29 |
|
30 |
--- a/drivers/gpu/drm/i915/gt/intel_reset.c |
31 |
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c |
32 |
@@ -278,6 +278,7 @@ out: |
33 |
static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask) |
34 |
{ |
35 |
struct intel_uncore *uncore = gt->uncore; |
36 |
+ int loops = 2; |
37 |
int err; |
38 |
|
39 |
/* |
40 |
@@ -285,18 +286,39 @@ static int gen6_hw_domain_reset(struct i |
41 |
* for fifo space for the write or forcewake the chip for |
42 |
* the read |
43 |
*/ |
44 |
- intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask); |
45 |
+ do { |
46 |
+ intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask); |
47 |
|
48 |
- /* Wait for the device to ack the reset requests */ |
49 |
- err = __intel_wait_for_register_fw(uncore, |
50 |
- GEN6_GDRST, hw_domain_mask, 0, |
51 |
- 500, 0, |
52 |
- NULL); |
53 |
+ /* |
54 |
+ * Wait for the device to ack the reset requests. |
55 |
+ * |
56 |
+ * On some platforms, e.g. Jasperlake, we see that the |
57 |
+ * engine register state is not cleared until shortly after |
58 |
+ * GDRST reports completion, causing a failure as we try |
59 |
+ * to immediately resume while the internal state is still |
60 |
+ * in flux. If we immediately repeat the reset, the second |
61 |
+ * reset appears to serialise with the first, and since |
62 |
+ * it is a no-op, the registers should retain their reset |
63 |
+ * value. However, there is still a concern that upon |
64 |
+ * leaving the second reset, the internal engine state |
65 |
+ * is still in flux and not ready for resuming. |
66 |
+ */ |
67 |
+ err = __intel_wait_for_register_fw(uncore, GEN6_GDRST, |
68 |
+ hw_domain_mask, 0, |
69 |
+ 2000, 0, |
70 |
+ NULL); |
71 |
+ } while (err == 0 && --loops); |
72 |
if (err) |
73 |
GT_TRACE(gt, |
74 |
"Wait for 0x%08x engines reset failed\n", |
75 |
hw_domain_mask); |
76 |
|
77 |
+ /* |
78 |
+ * As we have observed that the engine state is still volatile |
79 |
+ * after GDRST is acked, impose a small delay to let everything settle. |
80 |
+ */ |
81 |
+ udelay(50); |
82 |
+ |
83 |
return err; |
84 |
} |
85 |
|