summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSuman Tatiraju <sumant@codeaurora.org>2016-02-08 10:23:48 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:20:41 -0700
commit7cb32a408567f40c8a9f43d29872f3231614c087 (patch)
treed89d481e7657188a5bf490e8abd4decba60b63b4 /drivers
parent8a8cf1caab98aa85dede331807fa3c364511eb29 (diff)
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 <sumant@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/msm/adreno.c16
1 files 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;
}