diff options
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); +} |