Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d377ca6 authored by Lynus Vaz's avatar Lynus Vaz
Browse files

msm: kgsl: Avoid a deadlock with the cmdbatch timer



Don't take the cmdbatch lock while deleting the cmdbatch timer.
This avoids a deadlock where del_timer_sync() waits for the timer
function which needs to take the lock.

CRs-Fixed: 644944
Change-Id: Iaeb5a26b67e96e8e748fb9ff8c26fa8b0f2c3827
Signed-off-by: default avatarLynus Vaz <lvaz@codeaurora.org>
parent 3a86fb3f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -181,14 +181,15 @@ static inline struct kgsl_cmdbatch *adreno_dispatcher_get_cmdbatch(
			 */
			if (!timer_pending(&cmdbatch->timer))
				mod_timer(&cmdbatch->timer, jiffies + (5 * HZ));
			spin_unlock(&cmdbatch->lock);
		} else {
			/*
			 * Otherwise, delete the timer to make sure it is good
			 * and dead before queuing the buffer
			 */
			spin_unlock(&cmdbatch->lock);
			del_timer_sync(&cmdbatch->timer);
		}
		spin_unlock(&cmdbatch->lock);

		if (pending) {
			cmdbatch = ERR_PTR(-EAGAIN);
+9 −10
Original line number Diff line number Diff line
@@ -1401,12 +1401,14 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
	if (cmdbatch == NULL || cmdbatch->context == NULL)
		return;

	spin_lock(&cmdbatch->lock);
	if (list_empty(&cmdbatch->synclist))
		goto done;

	pr_err("kgsl: possible gpu syncpoint deadlock for context %d timestamp %d\n",
		cmdbatch->context->id, cmdbatch->timestamp);
	pr_err(" Active sync points:\n");

	spin_lock(&cmdbatch->lock);

	/* Print all the pending sync objects */
	list_for_each_entry(event, &cmdbatch->synclist, node) {

@@ -1431,6 +1433,7 @@ static void _kgsl_cmdbatch_timer(unsigned long data)
		}
	}

done:
	spin_unlock(&cmdbatch->lock);
}

@@ -1505,16 +1508,12 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
	}

	sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0;
	spin_unlock(&event->cmdbatch->lock);

	/*
	 * If the list is empty delete the canary timer while
	 * still holding the lock
	 */
	/* If the list is empty delete the canary timer */
	if (sched)
		del_timer_sync(&event->cmdbatch->timer);

	spin_unlock(&event->cmdbatch->lock);

	/*
	 * if this is the last event in the list then tell
	 * the GPU device that the cmdbatch can be submitted
@@ -1569,11 +1568,11 @@ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
	LIST_HEAD(cancel_synclist);
	int sched = 0;

	spin_lock(&cmdbatch->lock);

	/* Zap the canary timer */
	del_timer_sync(&cmdbatch->timer);

	spin_lock(&cmdbatch->lock);

	/* Empty the synclist before canceling events */
	list_splice_init(&cmdbatch->synclist, &cancel_synclist);
	spin_unlock(&cmdbatch->lock);