summaryrefslogtreecommitdiffstats
path: root/drivers/tee/tee_core.c
diff options
context:
space:
mode:
authorVolodymyr Babchuk <vlad.babchuk@gmail.com>2017-11-29 14:48:37 +0200
committerJens Wiklander <jens.wiklander@linaro.org>2017-12-15 13:36:18 +0100
commit217e0250cccb9e54d457991446cd3fab413085e1 (patch)
tree42906632546d8fe35890ac41a019f641fc1055a2 /drivers/tee/tee_core.c
parentf58e236c9d665ad0af99c908de4a9b6f07e74dda (diff)
downloadlinux-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.c40
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;
}