OSDN Git Service

msm: kgsl: Relax timestamp comparisons for processing events
authorJordan Crouse <jcrouse@codeaurora.org>
Wed, 11 May 2016 15:37:48 +0000 (09:37 -0600)
committerCarter Cooper <ccooper@codeaurora.org>
Wed, 20 Jul 2016 21:19:34 +0000 (15:19 -0600)
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>
drivers/gpu/msm/kgsl_events.c

index e1f9ad1..6f70b9d 100644 (file)
@@ -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) {