diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-08-04 23:50:17 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2019-08-04 23:50:17 -0700 |
commit | 8ea9ac46e6a737e1586683da03daa0bb639389fd (patch) | |
tree | cbcebeeabcc49ba4fbef844a45cb4c0e87fb52a5 | |
parent | 304503b0c7ee3c56b6fe0f8bb0bfa7695aab14a2 (diff) | |
parent | 56ed6c6274a95aab36894570481f351d3fb06e67 (diff) |
Merge "msm: kgsl: Fix race condition between drawobj and context destroy"LA.UM.7.9.r1-08000-sm6150.0
-rw-r--r-- | drivers/gpu/msm/kgsl_drawobj.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c index 7e89ac16eeb6..ee75a204635c 100644 --- a/drivers/gpu/msm/kgsl_drawobj.c +++ b/drivers/gpu/msm/kgsl_drawobj.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, 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 @@ -223,8 +223,13 @@ static void drawobj_sync_func(struct kgsl_device *device, trace_syncpoint_timestamp_expire(event->syncobj, event->context, event->timestamp); - drawobj_sync_expire(device, event); - kgsl_context_put(event->context); + /* + * Put down the context ref count only if + * this thread successfully clears the pending bit mask. + */ + if (drawobj_sync_expire(device, event)) + kgsl_context_put(event->context); + kgsl_drawobj_put(&event->syncobj->base); } @@ -254,33 +259,24 @@ static void drawobj_destroy_sparse(struct kgsl_drawobj *drawobj) static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) { struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); - unsigned long pending = 0; unsigned int i; /* Zap the canary timer */ del_timer_sync(&syncobj->timer); /* - * Copy off the pending list and clear each pending event atomically - - * this will render any subsequent asynchronous callback harmless. - * This marks each event for deletion. If any pending fence callbacks - * run between now and the actual cancel, the associated structures - * are kfreed only in the cancel call. - */ - for_each_set_bit(i, &syncobj->pending, KGSL_MAX_SYNCPOINTS) { - if (test_and_clear_bit(i, &syncobj->pending)) - __set_bit(i, &pending); - } - - /* * Clear all pending events - this will render any subsequent async * callbacks harmless */ for (i = 0; i < syncobj->numsyncs; i++) { struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i]; - /* Don't do anything if the event has already expired */ - if (!test_bit(i, &pending)) + /* + * Don't do anything if the event has already expired. + * If this thread clears the pending bit mask then it is + * responsible for doing context put. + */ + if (!test_and_clear_bit(i, &syncobj->pending)) continue; switch (event->type) { @@ -288,6 +284,11 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) kgsl_cancel_event(drawobj->device, &event->context->events, event->timestamp, drawobj_sync_func, event); + /* + * Do context put here to make sure the context is alive + * till this thread cancels kgsl event. + */ + kgsl_context_put(event->context); break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: kgsl_sync_fence_async_cancel(event->handle); @@ -300,7 +301,7 @@ static void drawobj_destroy_sync(struct kgsl_drawobj *drawobj) * If we cancelled an event, there's a good chance that the context is * on a dispatcher queue, so schedule to get it removed. */ - if (!bitmap_empty(&pending, KGSL_MAX_SYNCPOINTS) && + if (!bitmap_empty(&syncobj->pending, KGSL_MAX_SYNCPOINTS) && drawobj->device->ftbl->drawctxt_sched) drawobj->device->ftbl->drawctxt_sched(drawobj->device, drawobj->context); |