msm: kgsl: Prevent deadlock in cmdbatch timer

Dispatcher can acquire drawctxt->lock if context is pending
and the fence it is waiting on just got signalled.
Dispatcher acquires drawctxt->lock and tries to delete the
cmdbatch timer using delete_timer_sync(). Delete_timer_sync()
waits till timer and its pending handlers are deleted.
But if the timer expires at the same time, timer handler
could be waiting on drawctxt->lock leading to a
deadlock. To prevent this use spin_trylock_bh() instead of
spin_lock_bh(). spin_trylock_bh() does not wait for the lock
if it does not get it and allows the timer handler to finish.
This prevents the deadlock.

Change-Id: Ic2344fed5fccb581b58ec0b66b45ba68af9f1459
Signed-off-by: Tarun Karra <tkarra@codeaurora.org>
This commit is contained in:
Tarun Karra 2015-10-22 12:22:08 -07:00 committed by David Keitel
parent 880488a336
commit 1757ab898b

View file

@ -64,8 +64,22 @@ void adreno_drawctxt_dump(struct kgsl_device *device,
* We may have cmdbatch timer running, which also uses same * We may have cmdbatch timer running, which also uses same
* lock, take a lock with software interrupt disabled (bh) * lock, take a lock with software interrupt disabled (bh)
* to avoid spin lock recursion. * to avoid spin lock recursion.
*
* Use Spin trylock because dispatcher can acquire drawctxt->lock
* if context is pending and the fence it is waiting on just got
* signalled. Dispatcher acquires drawctxt->lock and tries to
* delete the cmdbatch timer using del_timer_sync().
* del_timer_sync() waits till timer and its pending handlers
* are deleted. But if the timer expires at the same time,
* timer handler could be waiting on drawctxt->lock leading to a
* deadlock. To prevent this use spin_trylock_bh.
*/ */
spin_lock_bh(&drawctxt->lock); if (!spin_trylock_bh(&drawctxt->lock)) {
dev_err(device->dev, " context[%d]: could not get lock\n",
context->id);
return;
}
dev_err(device->dev, dev_err(device->dev,
" context[%d]: queue=%d, submit=%d, start=%d, retire=%d\n", " context[%d]: queue=%d, submit=%d, start=%d, retire=%d\n",
context->id, queue, drawctxt->submitted_timestamp, context->id, queue, drawctxt->submitted_timestamp,