diff options
author | Volodymyr Babchuk <vlad.babchuk@gmail.com> | 2017-11-29 14:48:37 +0200 |
---|---|---|
committer | Jens Wiklander <jens.wiklander@linaro.org> | 2017-12-15 13:36:18 +0100 |
commit | 217e0250cccb9e54d457991446cd3fab413085e1 (patch) | |
tree | 42906632546d8fe35890ac41a019f641fc1055a2 /drivers/tee/tee_core.c | |
parent | f58e236c9d665ad0af99c908de4a9b6f07e74dda (diff) | |
download | linux-217e0250cccb9e54d457991446cd3fab413085e1.tar.gz linux-217e0250cccb9e54d457991446cd3fab413085e1.tar.bz2 linux-217e0250cccb9e54d457991446cd3fab413085e1.zip |
tee: use reference counting for tee_context
We need to ensure that tee_context is present until last
shared buffer will be freed.
Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'drivers/tee/tee_core.c')
-rw-r--r-- | drivers/tee/tee_core.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 295910f5cdd0..3d49ac2e3c84 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -54,6 +54,7 @@ static int tee_open(struct inode *inode, struct file *filp) goto err; } + kref_init(&ctx->refcount); ctx->teedev = teedev; INIT_LIST_HEAD(&ctx->list_shm); filp->private_data = ctx; @@ -68,19 +69,40 @@ err: return rc; } -static int tee_release(struct inode *inode, struct file *filp) +void teedev_ctx_get(struct tee_context *ctx) { - struct tee_context *ctx = filp->private_data; - struct tee_device *teedev = ctx->teedev; - struct tee_shm *shm; + if (ctx->releasing) + return; + + kref_get(&ctx->refcount); +} +static void teedev_ctx_release(struct kref *ref) +{ + struct tee_context *ctx = container_of(ref, struct tee_context, + refcount); + ctx->releasing = true; ctx->teedev->desc->ops->release(ctx); - mutex_lock(&ctx->teedev->mutex); - list_for_each_entry(shm, &ctx->list_shm, link) - shm->ctx = NULL; - mutex_unlock(&ctx->teedev->mutex); kfree(ctx); - tee_device_put(teedev); +} + +void teedev_ctx_put(struct tee_context *ctx) +{ + if (ctx->releasing) + return; + + kref_put(&ctx->refcount, teedev_ctx_release); +} + +static void teedev_close_context(struct tee_context *ctx) +{ + tee_device_put(ctx->teedev); + teedev_ctx_put(ctx); +} + +static int tee_release(struct inode *inode, struct file *filp) +{ + teedev_close_context(filp->private_data); return 0; } |