diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-01-18 23:55:07 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-01-18 23:55:07 +0000 |
commit | cc976e21ce92a62d8aa8541db5a82d3abe21d2c9 (patch) | |
tree | 3c5bb7cdf7520d87797a82bc7b43d589fda3191f | |
parent | 989c9267c863f167a02e191546301193efcd2587 (diff) |
drm/i915/gt: Reset twice
From Chris Wilson
4009502c091c1543ae8708a12d1a97583ae411ac in linux-6.1.y/6.1.7
d3de5616d36462a646f5b360ba82d3b09ff668eb in mainline linux
-rw-r--r-- | sys/dev/pci/drm/i915/gt/intel_reset.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/sys/dev/pci/drm/i915/gt/intel_reset.c b/sys/dev/pci/drm/i915/gt/intel_reset.c index 8862e89d4b2..843b00b15af 100644 --- a/sys/dev/pci/drm/i915/gt/intel_reset.c +++ b/sys/dev/pci/drm/i915/gt/intel_reset.c @@ -278,6 +278,7 @@ out: static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask) { struct intel_uncore *uncore = gt->uncore; + int loops = 2; int err; /* @@ -285,18 +286,39 @@ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask) * for fifo space for the write or forcewake the chip for * the read */ - intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask); + do { + intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask); - /* Wait for the device to ack the reset requests */ - err = __intel_wait_for_register_fw(uncore, - GEN6_GDRST, hw_domain_mask, 0, - 500, 0, - NULL); + /* + * Wait for the device to ack the reset requests. + * + * On some platforms, e.g. Jasperlake, we see that the + * engine register state is not cleared until shortly after + * GDRST reports completion, causing a failure as we try + * to immediately resume while the internal state is still + * in flux. If we immediately repeat the reset, the second + * reset appears to serialise with the first, and since + * it is a no-op, the registers should retain their reset + * value. However, there is still a concern that upon + * leaving the second reset, the internal engine state + * is still in flux and not ready for resuming. + */ + err = __intel_wait_for_register_fw(uncore, GEN6_GDRST, + hw_domain_mask, 0, + 2000, 0, + NULL); + } while (err == 0 && --loops); if (err) GT_TRACE(gt, "Wait for 0x%08x engines reset failed\n", hw_domain_mask); + /* + * As we have observed that the engine state is still volatile + * after GDRST is acked, impose a small delay to let everything settle. + */ + udelay(50); + return err; } |