0001
0002
0003
0004 #include <linux/slab.h>
0005
0006 #include "lima_device.h"
0007 #include "lima_ctx.h"
0008
0009 int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id)
0010 {
0011 struct lima_ctx *ctx;
0012 int i, err;
0013
0014 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
0015 if (!ctx)
0016 return -ENOMEM;
0017 ctx->dev = dev;
0018 kref_init(&ctx->refcnt);
0019
0020 for (i = 0; i < lima_pipe_num; i++) {
0021 err = lima_sched_context_init(dev->pipe + i, ctx->context + i, &ctx->guilty);
0022 if (err)
0023 goto err_out0;
0024 }
0025
0026 err = xa_alloc(&mgr->handles, id, ctx, xa_limit_32b, GFP_KERNEL);
0027 if (err < 0)
0028 goto err_out0;
0029
0030 ctx->pid = task_pid_nr(current);
0031 get_task_comm(ctx->pname, current);
0032
0033 return 0;
0034
0035 err_out0:
0036 for (i--; i >= 0; i--)
0037 lima_sched_context_fini(dev->pipe + i, ctx->context + i);
0038 kfree(ctx);
0039 return err;
0040 }
0041
0042 static void lima_ctx_do_release(struct kref *ref)
0043 {
0044 struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt);
0045 int i;
0046
0047 for (i = 0; i < lima_pipe_num; i++)
0048 lima_sched_context_fini(ctx->dev->pipe + i, ctx->context + i);
0049 kfree(ctx);
0050 }
0051
0052 int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id)
0053 {
0054 struct lima_ctx *ctx;
0055 int ret = 0;
0056
0057 mutex_lock(&mgr->lock);
0058 ctx = xa_erase(&mgr->handles, id);
0059 if (ctx)
0060 kref_put(&ctx->refcnt, lima_ctx_do_release);
0061 else
0062 ret = -EINVAL;
0063 mutex_unlock(&mgr->lock);
0064 return ret;
0065 }
0066
0067 struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id)
0068 {
0069 struct lima_ctx *ctx;
0070
0071 mutex_lock(&mgr->lock);
0072 ctx = xa_load(&mgr->handles, id);
0073 if (ctx)
0074 kref_get(&ctx->refcnt);
0075 mutex_unlock(&mgr->lock);
0076 return ctx;
0077 }
0078
0079 void lima_ctx_put(struct lima_ctx *ctx)
0080 {
0081 kref_put(&ctx->refcnt, lima_ctx_do_release);
0082 }
0083
0084 void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr)
0085 {
0086 mutex_init(&mgr->lock);
0087 xa_init_flags(&mgr->handles, XA_FLAGS_ALLOC);
0088 }
0089
0090 void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr)
0091 {
0092 struct lima_ctx *ctx;
0093 unsigned long id;
0094
0095 xa_for_each(&mgr->handles, id, ctx) {
0096 kref_put(&ctx->refcnt, lima_ctx_do_release);
0097 }
0098
0099 xa_destroy(&mgr->handles);
0100 mutex_destroy(&mgr->lock);
0101 }