diff options
| author | Dmitry Torokhov <[email protected]> | 2019-07-20 07:07:56 +0300 |
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2019-07-20 07:07:56 +0300 |
| commit | c39f2d9db0fd81ea20bb5cce9b3f082ca63753e2 (patch) | |
| tree | 8e80ed5601b4fb8880a2ca8e08802bc8b1f850bd /drivers/gpu/drm/lima/lima_ctx.c | |
| parent | 597473720f4dc69749542bfcfed4a927a43d935e (diff) | |
| parent | 771a081e44a9baa1991ef011cc453ef425591740 (diff) | |
Merge branch 'next' into for-linus
Prepare second round of input updates for 5.3 merge window.
Diffstat (limited to 'drivers/gpu/drm/lima/lima_ctx.c')
| -rw-r--r-- | drivers/gpu/drm/lima/lima_ctx.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c new file mode 100644 index 000000000000..22fff6caa961 --- /dev/null +++ b/drivers/gpu/drm/lima/lima_ctx.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* Copyright 2018-2019 Qiang Yu <[email protected]> */ + +#include <linux/slab.h> + +#include "lima_device.h" +#include "lima_ctx.h" + +int lima_ctx_create(struct lima_device *dev, struct lima_ctx_mgr *mgr, u32 *id) +{ + struct lima_ctx *ctx; + int i, err; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + ctx->dev = dev; + kref_init(&ctx->refcnt); + + for (i = 0; i < lima_pipe_num; i++) { + err = lima_sched_context_init(dev->pipe + i, ctx->context + i, &ctx->guilty); + if (err) + goto err_out0; + } + + err = xa_alloc(&mgr->handles, id, ctx, xa_limit_32b, GFP_KERNEL); + if (err < 0) + goto err_out0; + + return 0; + +err_out0: + for (i--; i >= 0; i--) + lima_sched_context_fini(dev->pipe + i, ctx->context + i); + kfree(ctx); + return err; +} + +static void lima_ctx_do_release(struct kref *ref) +{ + struct lima_ctx *ctx = container_of(ref, struct lima_ctx, refcnt); + int i; + + for (i = 0; i < lima_pipe_num; i++) + lima_sched_context_fini(ctx->dev->pipe + i, ctx->context + i); + kfree(ctx); +} + +int lima_ctx_free(struct lima_ctx_mgr *mgr, u32 id) +{ + struct lima_ctx *ctx; + int ret = 0; + + mutex_lock(&mgr->lock); + ctx = xa_erase(&mgr->handles, id); + if (ctx) + kref_put(&ctx->refcnt, lima_ctx_do_release); + else + ret = -EINVAL; + mutex_unlock(&mgr->lock); + return ret; +} + +struct lima_ctx *lima_ctx_get(struct lima_ctx_mgr *mgr, u32 id) +{ + struct lima_ctx *ctx; + + mutex_lock(&mgr->lock); + ctx = xa_load(&mgr->handles, id); + if (ctx) + kref_get(&ctx->refcnt); + mutex_unlock(&mgr->lock); + return ctx; +} + +void lima_ctx_put(struct lima_ctx *ctx) +{ + kref_put(&ctx->refcnt, lima_ctx_do_release); +} + +void lima_ctx_mgr_init(struct lima_ctx_mgr *mgr) +{ + mutex_init(&mgr->lock); + xa_init_flags(&mgr->handles, XA_FLAGS_ALLOC); +} + +void lima_ctx_mgr_fini(struct lima_ctx_mgr *mgr) +{ + struct lima_ctx *ctx; + unsigned long id; + + xa_for_each(&mgr->handles, id, ctx) { + kref_put(&ctx->refcnt, lima_ctx_do_release); + } + + xa_destroy(&mgr->handles); + mutex_destroy(&mgr->lock); +} |