From 16490341ab4f4019df12f3727a46a94713c8b145 Mon Sep 17 00:00:00 2001 From: Suman Tatiraju Date: Mon, 8 Feb 2016 10:23:48 -0800 Subject: [PATCH] msm: kgsl: Fix race condition in adreno_spin_idle() adreno_spin_idle spins for a timeout checking for gpu to idle. Sometimes due to race conditions the timeout can occur before the loop is executed. Change the logic to a do-while loop and add an extra idle check after the timeout before returning failure. CRs-Fixed: 955055 Change-Id: Idb92a0180dd8cc3e662b1ccf44d69e4bbafb29f1 Signed-off-by: Suman Tatiraju --- drivers/gpu/msm/adreno.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) 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; }