Merge "msm: kgsl: Avoid a deadlock with the cmdbatch timer"
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 1cc9663..5f80fcf 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -180,14 +180,15 @@
*/
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);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index d1241e0..543d6d7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1492,12 +1492,14 @@
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) {
@@ -1521,6 +1523,7 @@
}
}
+done:
spin_unlock(&cmdbatch->lock);
}
@@ -1596,16 +1599,12 @@
}
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
@@ -1648,11 +1647,11 @@
struct kgsl_cmdbatch_sync_event *event, *tmp;
LIST_HEAD(cancel_synclist);
- 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);