diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_reset.c')
| -rw-r--r-- | drivers/gpu/drm/i915/gt/intel_reset.c | 34 | 
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 24736ebee17c..78dc5e493c62 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/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;  }  | 
