msm: kgsl: Update internal timestamp when preemption is toggled

Say preemption is enabled and a context is bound to ringbuffer-1.
It's internal timestamp say is 0x4000. Now if we disable preemption,
all the contexts are bound to ringbuffer-0. Now, say the context
is going away. The context destroy path will check timestamp 0x4000
which is from the stale ringbuffer, against ringbuffer-0, and its very
likely that ringbuffer-0's timestamp is less than 0x4000 which will
cause a false context-detach fault. Fix this by updating the context's
internal timestamp to the last retired timestamp on the new ringbuffer.
Also, toggle preemption only if ringbuffers are completely drained.

Change-Id: I674978593b11df3998765017c270c3f0dde6c0a5
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
Harshdeep Dhatt 2020-09-03 21:05:00 -06:00
commit 8833b6fd82

View file

@ -144,16 +144,38 @@ static void change_preemption(struct adreno_device *adreno_dev, void *priv)
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_context *context;
struct adreno_context *drawctxt;
int id;
struct adreno_ringbuffer *rb;
int id, i, ret;
/* Make sure all ringbuffers are finished */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp,
2 * 1000);
if (ret) {
dev_err(device->dev,
"Cannot disable preemption because couldn't idle ringbuffer[%d] ret: %d\n",
rb->id, ret);
return;
}
}
change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);
adreno_dev->cur_rb = &adreno_dev->ringbuffers[0];
adreno_dev->next_rb = NULL;
adreno_dev->prev_rb = NULL;
/* Update the ringbuffer for each draw context */
write_lock(&device->context_lock);
idr_for_each_entry(&device->context_idr, context, id) {
drawctxt = ADRENO_CONTEXT(context);
drawctxt->rb = adreno_ctx_get_rb(adreno_dev, drawctxt);
/*
* Make sure context destroy checks against the correct
* ringbuffer's timestamp.
*/
adreno_rb_readtimestamp(adreno_dev, drawctxt->rb,
KGSL_TIMESTAMP_RETIRED, &drawctxt->internal_timestamp);
}
write_unlock(&device->context_lock);
}