diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_submitqueue.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_submitqueue.c | 135 | 
1 files changed, 135 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c new file mode 100644 index 000000000000..593c3b5f44cd --- /dev/null +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -0,0 +1,135 @@ +/* Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + */ + +#include <linux/kref.h> +#include "msm_gpu.h" + +void msm_submitqueue_destroy(struct kref *kref) +{ +	struct msm_gpu_submitqueue *queue = container_of(kref, +		struct msm_gpu_submitqueue, ref); + +	kfree(queue); +} + +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, +		u32 id) +{ +	struct msm_gpu_submitqueue *entry; + +	if (!ctx) +		return NULL; + +	read_lock(&ctx->queuelock); + +	list_for_each_entry(entry, &ctx->submitqueues, node) { +		if (entry->id == id) { +			kref_get(&entry->ref); +			read_unlock(&ctx->queuelock); + +			return entry; +		} +	} + +	read_unlock(&ctx->queuelock); +	return NULL; +} + +void msm_submitqueue_close(struct msm_file_private *ctx) +{ +	struct msm_gpu_submitqueue *entry, *tmp; + +	if (!ctx) +		return; + +	/* +	 * No lock needed in close and there won't +	 * be any more user ioctls coming our way +	 */ +	list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) +		msm_submitqueue_put(entry); +} + +int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio, u32 flags, +		u32 *id) +{ +	struct msm_gpu_submitqueue *queue; + +	if (!ctx) +		return -ENODEV; + +	queue = kzalloc(sizeof(*queue), GFP_KERNEL); + +	if (!queue) +		return -ENOMEM; + +	kref_init(&queue->ref); +	queue->flags = flags; +	queue->prio = prio; + +	write_lock(&ctx->queuelock); + +	queue->id = ctx->queueid++; + +	if (id) +		*id = queue->id; + +	list_add_tail(&queue->node, &ctx->submitqueues); + +	write_unlock(&ctx->queuelock); + +	return 0; +} + +int msm_submitqueue_init(struct msm_file_private *ctx) +{ +	if (!ctx) +		return 0; + +	INIT_LIST_HEAD(&ctx->submitqueues); + +	rwlock_init(&ctx->queuelock); + +	return msm_submitqueue_create(ctx, 2, 0, NULL); +} + +int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id) +{ +	struct msm_gpu_submitqueue *entry; + +	if (!ctx) +		return 0; + +	/* +	 * id 0 is the "default" queue and can't be destroyed +	 * by the user +	 */ +	if (!id) +		return -ENOENT; + +	write_lock(&ctx->queuelock); + +	list_for_each_entry(entry, &ctx->submitqueues, node) { +		if (entry->id == id) { +			list_del(&entry->node); +			write_unlock(&ctx->queuelock); + +			msm_submitqueue_put(entry); +			return 0; +		} +	} + +	write_unlock(&ctx->queuelock); +	return -ENOENT; +} +  | 
