msm: kgsl: Fix context reference counting

Get rid of kgsl_find_context. Use instead kgsl_context_get that does
correct RCU read locking around the itr_find and increases the
reference count on the context before returning it.  This eliminates
the chance that a context will be destroyed while somebody is still
using it.  Of course increased use of kgsl_context_get is accompanied
by kgsl_context_put in all the right places.

Change-Id: Ic0dedbad73d497fd9b451aefad8e5b28d33b829d
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index b1b11cc..c5b7e91 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -59,7 +59,7 @@
 		return -EINVAL;
 
 	if (id != KGSL_MEMSTORE_GLOBAL) {
-		context = idr_find(&device->context_idr, id);
+		context = kgsl_context_get(device, id);
 		if (context == NULL)
 			return -EINVAL;
 	}
@@ -75,12 +75,15 @@
 	if (timestamp_cmp(cur_ts, ts) >= 0) {
 		trace_kgsl_fire_event(id, ts, 0);
 		cb(device, priv, id, ts);
+		kgsl_context_put(context);
 		return 0;
 	}
 
 	event = kzalloc(sizeof(*event), GFP_KERNEL);
-	if (event == NULL)
+	if (event == NULL) {
+		kgsl_context_put(context);
 		return -ENOMEM;
+	}
 
 	event->context = context;
 	event->timestamp = ts;
@@ -91,10 +94,6 @@
 
 	trace_kgsl_register_event(id, ts);
 
-	/* inc refcount to avoid race conditions in cleanup */
-	if (context)
-		kgsl_context_get(context);
-
 	/* Add the event to either the owning context or the global list */
 
 	if (context) {
@@ -143,7 +142,7 @@
 	 * Increment the refcount to avoid freeing the context while
 	 * cancelling its events
 	 */
-	kgsl_context_get(context);
+	_kgsl_context_get(context);
 
 	/* Remove ourselves from the master pending list */
 	list_del_init(&context->events_list);
@@ -320,7 +319,7 @@
 		 * Increment the refcount to make sure that the list_del_init
 		 * is called with a valid context's list
 		 */
-		kgsl_context_get(context);
+		_kgsl_context_get(context);
 		/*
 		 * If kgsl_timestamp_expired_context returns 0 then it no longer
 		 * has any pending events and can be removed from the list