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