mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
msm: kgsl: Don't silently ignore events that have a retired timestamp
After all the current events are processed in the main loop, the next pending event is marked to fire an interrupt to start the cycle anew. When the event is marked, we check the timestamp again to make sure that we are always caught up with the GPU. If the timestamp for the next event happens to be retired when we get to this point, we silently leave the function. If there are no other subsequent events or waittimestamp requests, then it is possible that another interrupt might never be fired for that context and then the event gets missed. Return a 1 in this case all the way back up the stack and make the event code keep processing events until we are positive that none are past. Change-Id: I5a770e7f06612e1aecbfe2e8ccbfeebdab3fc9fc CRs-Fixed: 441191 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
parent
07531fbafe
commit
6ded9eb5ac
3 changed files with 27 additions and 10 deletions
|
@ -2620,10 +2620,11 @@ static unsigned int adreno_check_hw_ts(struct kgsl_device *device,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void adreno_next_event(struct kgsl_device *device,
|
||||
/* Return 1 if the event timestmp has already passed, 0 if it was marked */
|
||||
static int adreno_next_event(struct kgsl_device *device,
|
||||
struct kgsl_event *event)
|
||||
{
|
||||
adreno_check_hw_ts(device, event->context, event->timestamp);
|
||||
return adreno_check_hw_ts(device, event->context, event->timestamp);
|
||||
}
|
||||
|
||||
static int adreno_check_interrupt_timestamp(struct kgsl_device *device,
|
||||
|
|
|
@ -114,7 +114,7 @@ struct kgsl_functable {
|
|||
enum kgsl_property_type type, void *value,
|
||||
unsigned int sizebytes);
|
||||
int (*postmortem_dump) (struct kgsl_device *device, int manual);
|
||||
void (*next_event)(struct kgsl_device *device,
|
||||
int (*next_event)(struct kgsl_device *device,
|
||||
struct kgsl_event *event);
|
||||
};
|
||||
|
||||
|
|
|
@ -218,27 +218,43 @@ static void _process_event_list(struct kgsl_device *device,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void _mark_next_event(struct kgsl_device *device,
|
||||
static inline int _mark_next_event(struct kgsl_device *device,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct kgsl_event *event;
|
||||
|
||||
if (!list_empty(head)) {
|
||||
event = list_first_entry(head, struct kgsl_event, list);
|
||||
device->ftbl->next_event(device, event);
|
||||
|
||||
/*
|
||||
* Next event will return 0 if the event was marked or 1 if the
|
||||
* timestamp on the event has passed - return that up a layer
|
||||
*/
|
||||
|
||||
return device->ftbl->next_event(device, event);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kgsl_process_context_events(struct kgsl_device *device,
|
||||
struct kgsl_context *context)
|
||||
{
|
||||
unsigned int timestamp = kgsl_readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
while (1) {
|
||||
unsigned int timestamp = kgsl_readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
_process_event_list(device, &context->events, timestamp);
|
||||
_process_event_list(device, &context->events, timestamp);
|
||||
|
||||
/* Mark the next pending event on the list to fire an interrupt */
|
||||
_mark_next_event(device, &context->events);
|
||||
/*
|
||||
* _mark_next event will return 1 as long as the next event
|
||||
* timestamp has expired - this is to cope with an unavoidable
|
||||
* race condition with the GPU that is still processing events.
|
||||
*/
|
||||
|
||||
if (!_mark_next_event(device, &context->events))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if the list is empty so the calling function can remove the
|
||||
|
|
Loading…
Reference in a new issue