diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 6f8919a3cc66..69a52b725723 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -3024,7 +3024,7 @@ int adreno_idle(struct kgsl_device *device) adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, 0x110, 0x110); - while (time_before(jiffies, wait)) { + do { /* * If we fault, stop waiting and return an error. The dispatcher * will clean up the fault from the work queue, but we need to @@ -3037,7 +3037,19 @@ int adreno_idle(struct kgsl_device *device) if (adreno_isidle(device)) return 0; - } + + } while (time_before(jiffies, wait)); + + /* + * Under rare conditions, preemption can cause the while loop to exit + * without checking if the gpu is idle. check one last time before we + * return failure. + */ + if (adreno_gpu_fault(adreno_dev) != 0) + return -EDEADLK; + + if (adreno_isidle(device)) + return 0; return -ETIMEDOUT; }