]>
Commit | Line | Data |
---|---|---|
f7de1545 JC |
1 | /* 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 | ||
17 | void 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 | ||
25 | struct 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 | ||
48 | void 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 | ||
f97decac JC |
63 | int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, |
64 | u32 prio, u32 flags, u32 *id) | |
f7de1545 | 65 | { |
f97decac | 66 | struct msm_drm_private *priv = drm->dev_private; |
f7de1545 JC |
67 | struct msm_gpu_submitqueue *queue; |
68 | ||
69 | if (!ctx) | |
70 | return -ENODEV; | |
71 | ||
72 | queue = kzalloc(sizeof(*queue), GFP_KERNEL); | |
73 | ||
74 | if (!queue) | |
75 | return -ENOMEM; | |
76 | ||
77 | kref_init(&queue->ref); | |
78 | queue->flags = flags; | |
f97decac JC |
79 | |
80 | if (priv->gpu) { | |
81 | if (prio >= priv->gpu->nr_rings) | |
82 | return -EINVAL; | |
83 | ||
84 | queue->prio = prio; | |
85 | } | |
f7de1545 JC |
86 | |
87 | write_lock(&ctx->queuelock); | |
88 | ||
89 | queue->id = ctx->queueid++; | |
90 | ||
91 | if (id) | |
92 | *id = queue->id; | |
93 | ||
94 | list_add_tail(&queue->node, &ctx->submitqueues); | |
95 | ||
96 | write_unlock(&ctx->queuelock); | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
f97decac | 101 | int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx) |
f7de1545 | 102 | { |
f97decac JC |
103 | struct msm_drm_private *priv = drm->dev_private; |
104 | int default_prio; | |
105 | ||
f7de1545 JC |
106 | if (!ctx) |
107 | return 0; | |
108 | ||
f97decac JC |
109 | /* |
110 | * Select priority 2 as the "default priority" unless nr_rings is less | |
111 | * than 2 and then pick the lowest pirority | |
112 | */ | |
113 | default_prio = priv->gpu ? | |
114 | clamp_t(uint32_t, 2, 0, priv->gpu->nr_rings - 1) : 0; | |
115 | ||
f7de1545 JC |
116 | INIT_LIST_HEAD(&ctx->submitqueues); |
117 | ||
118 | rwlock_init(&ctx->queuelock); | |
119 | ||
f97decac | 120 | return msm_submitqueue_create(drm, ctx, default_prio, 0, NULL); |
f7de1545 JC |
121 | } |
122 | ||
123 | int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id) | |
124 | { | |
125 | struct msm_gpu_submitqueue *entry; | |
126 | ||
127 | if (!ctx) | |
128 | return 0; | |
129 | ||
130 | /* | |
131 | * id 0 is the "default" queue and can't be destroyed | |
132 | * by the user | |
133 | */ | |
134 | if (!id) | |
135 | return -ENOENT; | |
136 | ||
137 | write_lock(&ctx->queuelock); | |
138 | ||
139 | list_for_each_entry(entry, &ctx->submitqueues, node) { | |
140 | if (entry->id == id) { | |
141 | list_del(&entry->node); | |
142 | write_unlock(&ctx->queuelock); | |
143 | ||
144 | msm_submitqueue_put(entry); | |
145 | return 0; | |
146 | } | |
147 | } | |
148 | ||
149 | write_unlock(&ctx->queuelock); | |
150 | return -ENOENT; | |
151 | } | |
152 |