From 6dbd07cf208295c89611a3a51e92bee176be3eb6 Mon Sep 17 00:00:00 2001
From: Lucille Sylvester <lsylvest@codeaurora.org>
Date: Wed, 18 Jun 2014 16:17:05 -0600
Subject: [PATCH] msm: kgsl: fix MIN power constraints in non-trivial cases

Switching from a MAX to a MIN power constraint in the same
context is broken.  So is switching from a MAX context constraint
to a MIN constraint on a different context.  Clarify constraint
ownership, update the timestamps accordingly, and reset constraints
when changed by the context.

Change-Id: Id27dbc20e2aac994101817af3857451c1703219e
Signed-off-by: Lucille Sylvester <lsylvest@codeaurora.org>
---
 drivers/gpu/msm/adreno.c            |  5 +++++
 drivers/gpu/msm/adreno_ringbuffer.c | 18 +++++++++++++-----
 drivers/gpu/msm/kgsl_pwrctrl.h      |  1 +
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 110464d6ac7a..45b6c0aeee72 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2283,6 +2283,11 @@ static int adreno_set_constraint(struct kgsl_device *device,
 		break;
 	}
 
+	/* If a new constraint has been set for a context, cancel the old one */
+	if ((status == 0) &&
+		(context->id == device->pwrctrl.constraint.owner_id))
+		device->pwrctrl.constraint.type = KGSL_CONSTRAINT_NONE;
+
 	return status;
 }
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index a55c9d2f9db3..60aa618f517d 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1173,8 +1173,9 @@ void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
 		constraint = adreno_ringbuffer_get_constraint(device, context);
 
 		/*
-		 * If a constraint is already set, set a new
-		 * constraint only if it is faster
+		 * If a constraint is already set, set a new constraint only
+		 * if it is faster.  If the requested constraint is the same
+		 * as the current one, update ownership and timestamp.
 		 */
 		if ((device->pwrctrl.constraint.type ==
 			KGSL_CONSTRAINT_NONE) || (constraint <
@@ -1185,10 +1186,17 @@ void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
 					context->pwr_constraint.type;
 			device->pwrctrl.constraint.hint.
 					pwrlevel.level = constraint;
+			device->pwrctrl.constraint.owner_id = context->id;
+			device->pwrctrl.constraint.expires = jiffies +
+					device->pwrctrl.interval_timeout;
+		} else if ((device->pwrctrl.constraint.type ==
+				context->pwr_constraint.type) &&
+			(device->pwrctrl.constraint.hint.pwrlevel.level ==
+				constraint)) {
+			device->pwrctrl.constraint.owner_id = context->id;
+			device->pwrctrl.constraint.expires = jiffies +
+					device->pwrctrl.interval_timeout;
 		}
-
-		device->pwrctrl.constraint.expires = jiffies +
-			device->pwrctrl.interval_timeout;
 	}
 
 }
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index f5e7bbc02b36..ece58fafa321 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -61,6 +61,7 @@ struct kgsl_pwr_constraint {
 		} pwrlevel;
 	} hint;
 	unsigned long expires;
+	uint32_t owner_id;
 };
 
 /**
-- 
GitLab