summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Crouse <jcrouse@codeaurora.org>2016-05-11 09:37:48 -0600
committerCarter Cooper <ccooper@codeaurora.org>2016-07-20 15:19:34 -0600
commit75437b98b172befd87c304066272c756613ac604 (patch)
treefdb0f70b2285a88620494fc24c39b6a86f0be3fd
parent858b8e026414b3cdc554fdd52e2254ec7b16faeb (diff)
msm: kgsl: Relax timestamp comparisons for processing events
When processing an event group we check the previously processed timestamp to avoid going through the loop if we don't need to. We use timestamp_cmp() to check the timestamp. In situations where the retired timestamp has advanced by more than 0x80000000 since the last time we checked the timestamp, timestamp_cmp() will return -1 as it thinks that the new timestamp is older than the processed timestamp. This can happen with certain tests and scheduling hiccups. The event processor can be much less restrictive - all we really care about is that the retired timestamp didn't slip backwards by accident (highly unlikely). So just check that the last proccessed timestamp is not equal to the retired timestamp and if the retired timestamp has already rolled, that the delta is outside of the 0x8000000 window. CRs-Fixed: 1009149 Change-Id: Ic0dedbad641bfa3fd6cbc1c91a37fb0e37f72bae Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
-rw-r--r--drivers/gpu/msm/kgsl_events.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index e1f9ad17d0ff..6f70b9ddd376 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,6 +56,23 @@ static void _kgsl_event_worker(struct work_struct *work)
kmem_cache_free(events_cache, event);
}
+/* return true if the group needs to be processed */
+static bool _do_process_group(unsigned int processed, unsigned int cur)
+{
+ if (processed == cur)
+ return false;
+
+ /*
+ * This ensures that the timestamp didn't slip back accidently, maybe
+ * due to a memory barrier issue. This is highly unlikely but we've
+ * been burned here in the past.
+ */
+ if ((cur < processed) && ((processed - cur) < KGSL_TIMESTAMP_WINDOW))
+ return false;
+
+ return true;
+}
+
static void _process_event_group(struct kgsl_device *device,
struct kgsl_event_group *group, bool flush)
{
@@ -80,11 +97,7 @@ static void _process_event_group(struct kgsl_device *device,
group->readtimestamp(device, group->priv, KGSL_TIMESTAMP_RETIRED,
&timestamp);
- /*
- * If no timestamps have been retired since the last time we were here
- * then we can avoid going through this loop
- */
- if (!flush && timestamp_cmp(timestamp, group->processed) <= 0)
+ if (!flush && _do_process_group(group->processed, timestamp) == false)
goto out;
list_for_each_entry_safe(event, tmp, &group->events, node) {