From 7cb32a408567f40c8a9f43d29872f3231614c087 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: 978122 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 ba2533bd4c4c..337a7f2023f7 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2165,7 +2165,7 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, 0x00000000, 0x80000000); - 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 @@ -2178,7 +2178,19 @@ int adreno_spin_idle(struct adreno_device *adreno_dev, unsigned int timeout) if (adreno_isidle(KGSL_DEVICE(adreno_dev))) 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(KGSL_DEVICE(adreno_dev))) + return 0; return -ETIMEDOUT; }