1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 /* Copyright 2018-2019 Qiang Yu <yuq825@gmail.com> */ 3 4 #include <linux/slab.h> 5 6 #include "lima_device.h" 7 #include "lima_ctx.h" 8 9 int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id) 10 { 11 struct lima_ctx *ctx; 12 int i, err; 13 14 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 15 if (!ctx) 16 return -ENOMEM; 17 ctx->dev = dev; 18 kref_init(&ctx->refcnt); 19 20 for (i = 0; i < lima_pipe_num; i++) { 21 err = lima_sched_context_init(dev->pipe + i, ctx->context + i, &ctx->guilty); 22 if (err) 23 goto err_out0; 24 } 25 26 err = xa_alloc(&mgr->handles, id, ctx, xa_limit_32b, GFP_KERNEL); 27 if (err < 0) 28 goto err_out0; 29 30 return 0; 31 32 err_out0: 33 for (i--; i >= 0; i--) 34 lima_sched_context_fini(dev->pipe + i, ctx->context + i); 35 kfree(ctx); 36 return err; 37 } 38 39 static void lima_ctx_do_release(struct kref *ref) 40 { 41 struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt); 42 int i; 43 44 for (i = 0; i < lima_pipe_num; i++) 45 lima_sched_context_fini(ctx->dev->pipe + i, ctx->context + i); 46 kfree(ctx); 47 } 48 49 int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id) 50 { 51 struct lima_ctx *ctx; 52 int ret = 0; 53 54 mutex_lock(&mgr->lock); 55 ctx = xa_erase(&mgr->handles, id); 56 if (ctx) 57 kref_put(&ctx->refcnt, lima_ctx_do_release); 58 else 59 ret = -EINVAL; 60 mutex_unlock(&mgr->lock); 61 return ret; 62 } 63 64 struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id) 65 { 66 struct lima_ctx *ctx; 67 68 mutex_lock(&mgr->lock); 69 ctx = xa_load(&mgr->handles, id); 70 if (ctx) 71 kref_get(&ctx->refcnt); 72 mutex_unlock(&mgr->lock); 73 return ctx; 74 } 75 76 void lima_ctx_put(struct lima_ctx *ctx) 77 { 78 kref_put(&ctx->refcnt, lima_ctx_do_release); 79 } 80 81 void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr) 82 { 83 mutex_init(&mgr->lock); 84 xa_init_flags(&mgr->handles, XA_FLAGS_ALLOC); 85 } 86 87 void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr) 88 { 89 struct lima_ctx *ctx; 90 unsigned long id; 91 92 xa_for_each(&mgr->handles, id, ctx) { 93 kref_put(&ctx->refcnt, lima_ctx_do_release); 94 } 95 96 xa_destroy(&mgr->handles); 97 mutex_destroy(&mgr->lock); 98 } 99