blob: 593c3b5f44cdc1f4a123c92d68c448c002cbe17d [file] [log] [blame]
Jordan Crousef7de1542017-10-20 11:06:55 -06001/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/kref.h>
15#include "msm_gpu.h"
16
17void msm_submitqueue_destroy(struct kref *kref)
18{
19 struct msm_gpu_submitqueue *queue = container_of(kref,
20 struct msm_gpu_submitqueue, ref);
21
22 kfree(queue);
23}
24
25struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx,
26 u32 id)
27{
28 struct msm_gpu_submitqueue *entry;
29
30 if (!ctx)
31 return NULL;
32
33 read_lock(&ctx->queuelock);
34
35 list_for_each_entry(entry, &ctx->submitqueues, node) {
36 if (entry->id == id) {
37 kref_get(&entry->ref);
38 read_unlock(&ctx->queuelock);
39
40 return entry;
41 }
42 }
43
44 read_unlock(&ctx->queuelock);
45 return NULL;
46}
47
48void msm_submitqueue_close(struct msm_file_private *ctx)
49{
50 struct msm_gpu_submitqueue *entry, *tmp;
51
52 if (!ctx)
53 return;
54
55 /*
56 * No lock needed in close and there won't
57 * be any more user ioctls coming our way
58 */
59 list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
60 msm_submitqueue_put(entry);
61}
62
63int msm_submitqueue_create(struct msm_file_private *ctx, u32 prio, u32 flags,
64 u32 *id)
65{
66 struct msm_gpu_submitqueue *queue;
67
68 if (!ctx)
69 return -ENODEV;
70
71 queue = kzalloc(sizeof(*queue), GFP_KERNEL);
72
73 if (!queue)
74 return -ENOMEM;
75
76 kref_init(&queue->ref);
77 queue->flags = flags;
78 queue->prio = prio;
79
80 write_lock(&ctx->queuelock);
81
82 queue->id = ctx->queueid++;
83
84 if (id)
85 *id = queue->id;
86
87 list_add_tail(&queue->node, &ctx->submitqueues);
88
89 write_unlock(&ctx->queuelock);
90
91 return 0;
92}
93
94int msm_submitqueue_init(struct msm_file_private *ctx)
95{
96 if (!ctx)
97 return 0;
98
99 INIT_LIST_HEAD(&ctx->submitqueues);
100
101 rwlock_init(&ctx->queuelock);
102
103 return msm_submitqueue_create(ctx, 2, 0, NULL);
104}
105
106int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id)
107{
108 struct msm_gpu_submitqueue *entry;
109
110 if (!ctx)
111 return 0;
112
113 /*
114 * id 0 is the "default" queue and can't be destroyed
115 * by the user
116 */
117 if (!id)
118 return -ENOENT;
119
120 write_lock(&ctx->queuelock);
121
122 list_for_each_entry(entry, &ctx->submitqueues, node) {
123 if (entry->id == id) {
124 list_del(&entry->node);
125 write_unlock(&ctx->queuelock);
126
127 msm_submitqueue_put(entry);
128 return 0;
129 }
130 }
131
132 write_unlock(&ctx->queuelock);
133 return -ENOENT;
134}
135