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(size: sizeof(*ctx), GFP_KERNEL); |
15 | if (!ctx) |
16 | return -ENOMEM; |
17 | ctx->dev = dev; |
18 | kref_init(kref: &ctx->refcnt); |
19 | |
20 | for (i = 0; i < lima_pipe_num; i++) { |
21 | err = lima_sched_context_init(pipe: dev->pipe + i, context: ctx->context + i, guilty: &ctx->guilty); |
22 | if (err) |
23 | goto err_out0; |
24 | } |
25 | |
26 | err = xa_alloc(xa: &mgr->handles, id, entry: ctx, xa_limit_32b, GFP_KERNEL); |
27 | if (err < 0) |
28 | goto err_out0; |
29 | |
30 | ctx->pid = task_pid_nr(current); |
31 | get_task_comm(ctx->pname, current); |
32 | |
33 | return 0; |
34 | |
35 | err_out0: |
36 | for (i--; i >= 0; i--) |
37 | lima_sched_context_fini(pipe: dev->pipe + i, context: ctx->context + i); |
38 | kfree(objp: ctx); |
39 | return err; |
40 | } |
41 | |
42 | static void lima_ctx_do_release(struct kref *ref) |
43 | { |
44 | struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt); |
45 | int i; |
46 | |
47 | for (i = 0; i < lima_pipe_num; i++) |
48 | lima_sched_context_fini(pipe: ctx->dev->pipe + i, context: ctx->context + i); |
49 | kfree(objp: ctx); |
50 | } |
51 | |
52 | int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id) |
53 | { |
54 | struct lima_ctx *ctx; |
55 | int ret = 0; |
56 | |
57 | mutex_lock(&mgr->lock); |
58 | ctx = xa_erase(&mgr->handles, index: id); |
59 | if (ctx) |
60 | kref_put(kref: &ctx->refcnt, release: lima_ctx_do_release); |
61 | else |
62 | ret = -EINVAL; |
63 | mutex_unlock(lock: &mgr->lock); |
64 | return ret; |
65 | } |
66 | |
67 | struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id) |
68 | { |
69 | struct lima_ctx *ctx; |
70 | |
71 | mutex_lock(&mgr->lock); |
72 | ctx = xa_load(&mgr->handles, index: id); |
73 | if (ctx) |
74 | kref_get(kref: &ctx->refcnt); |
75 | mutex_unlock(lock: &mgr->lock); |
76 | return ctx; |
77 | } |
78 | |
79 | void lima_ctx_put(struct lima_ctx *ctx) |
80 | { |
81 | kref_put(kref: &ctx->refcnt, release: lima_ctx_do_release); |
82 | } |
83 | |
84 | void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr) |
85 | { |
86 | mutex_init(&mgr->lock); |
87 | xa_init_flags(xa: &mgr->handles, XA_FLAGS_ALLOC); |
88 | } |
89 | |
90 | void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr) |
91 | { |
92 | struct lima_ctx *ctx; |
93 | unsigned long id; |
94 | |
95 | xa_for_each(&mgr->handles, id, ctx) { |
96 | kref_put(kref: &ctx->refcnt, release: lima_ctx_do_release); |
97 | } |
98 | |
99 | xa_destroy(&mgr->handles); |
100 | mutex_destroy(lock: &mgr->lock); |
101 | } |
102 | |