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