diff options
author | Suman Tatiraju <sumant@codeaurora.org> | 2016-02-08 10:23:48 -0800 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:20:41 -0700 |
commit | 7cb32a408567f40c8a9f43d29872f3231614c087 (patch) | |
tree | d89d481e7657188a5bf490e8abd4decba60b63b4 /drivers | |
parent | 8a8cf1caab98aa85dede331807fa3c364511eb29 (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.c | 16 |
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; } |