1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/types.h>
29#include <linux/slab.h>
30#include <linux/mm.h>
31#include <linux/uaccess.h>
32#include <linux/fs.h>
33#include <linux/file.h>
34#include <linux/module.h>
35#include <linux/mman.h>
36#include <linux/pagemap.h>
37#include "drmP.h"
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71int
72drm_gem_init(struct drm_device *dev)
73{
74 spin_lock_init(&dev->object_name_lock);
75 idr_init(&dev->object_name_idr);
76 atomic_set(&dev->object_count, 0);
77 atomic_set(&dev->object_memory, 0);
78 atomic_set(&dev->pin_count, 0);
79 atomic_set(&dev->pin_memory, 0);
80 atomic_set(&dev->gtt_count, 0);
81 atomic_set(&dev->gtt_memory, 0);
82 return 0;
83}
84
85
86
87
88struct drm_gem_object *
89drm_gem_object_alloc(struct drm_device *dev, size_t size)
90{
91 struct drm_gem_object *obj;
92
93 BUG_ON((size & (PAGE_SIZE - 1)) != 0);
94
95 obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
96
97 obj->dev = dev;
98 obj->filp = shmem_file_setup("drm mm object", size, 0);
99 if (IS_ERR(obj->filp)) {
100 kfree(obj);
101 return NULL;
102 }
103
104 kref_init(&obj->refcount);
105 kref_init(&obj->handlecount);
106 obj->size = size;
107 if (dev->driver->gem_init_object != NULL &&
108 dev->driver->gem_init_object(obj) != 0) {
109 fput(obj->filp);
110 kfree(obj);
111 return NULL;
112 }
113 atomic_inc(&dev->object_count);
114 atomic_add(obj->size, &dev->object_memory);
115 return obj;
116}
117EXPORT_SYMBOL(drm_gem_object_alloc);
118
119
120
121
122static int
123drm_gem_handle_delete(struct drm_file *filp, int handle)
124{
125 struct drm_device *dev;
126 struct drm_gem_object *obj;
127
128
129
130
131
132
133
134
135
136
137 spin_lock(&filp->table_lock);
138
139
140 obj = idr_find(&filp->object_idr, handle);
141 if (obj == NULL) {
142 spin_unlock(&filp->table_lock);
143 return -EINVAL;
144 }
145 dev = obj->dev;
146
147
148 idr_remove(&filp->object_idr, handle);
149 spin_unlock(&filp->table_lock);
150
151 mutex_lock(&dev->struct_mutex);
152 drm_gem_object_handle_unreference(obj);
153 mutex_unlock(&dev->struct_mutex);
154
155 return 0;
156}
157
158
159
160
161
162
163int
164drm_gem_handle_create(struct drm_file *file_priv,
165 struct drm_gem_object *obj,
166 int *handlep)
167{
168 int ret;
169
170
171
172
173again:
174
175 if (idr_pre_get(&file_priv->object_idr, GFP_KERNEL) == 0)
176 return -ENOMEM;
177
178
179 spin_lock(&file_priv->table_lock);
180 ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
181 spin_unlock(&file_priv->table_lock);
182 if (ret == -EAGAIN)
183 goto again;
184
185 if (ret != 0)
186 return ret;
187
188 drm_gem_object_handle_reference(obj);
189 return 0;
190}
191EXPORT_SYMBOL(drm_gem_handle_create);
192
193
194struct drm_gem_object *
195drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
196 int handle)
197{
198 struct drm_gem_object *obj;
199
200 spin_lock(&filp->table_lock);
201
202
203 obj = idr_find(&filp->object_idr, handle);
204 if (obj == NULL) {
205 spin_unlock(&filp->table_lock);
206 return NULL;
207 }
208
209 drm_gem_object_reference(obj);
210
211 spin_unlock(&filp->table_lock);
212
213 return obj;
214}
215EXPORT_SYMBOL(drm_gem_object_lookup);
216
217
218
219
220int
221drm_gem_close_ioctl(struct drm_device *dev, void *data,
222 struct drm_file *file_priv)
223{
224 struct drm_gem_close *args = data;
225 int ret;
226
227 if (!(dev->driver->driver_features & DRIVER_GEM))
228 return -ENODEV;
229
230 ret = drm_gem_handle_delete(file_priv, args->handle);
231
232 return ret;
233}
234
235
236
237
238
239
240
241int
242drm_gem_flink_ioctl(struct drm_device *dev, void *data,
243 struct drm_file *file_priv)
244{
245 struct drm_gem_flink *args = data;
246 struct drm_gem_object *obj;
247 int ret;
248
249 if (!(dev->driver->driver_features & DRIVER_GEM))
250 return -ENODEV;
251
252 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
253 if (obj == NULL)
254 return -EBADF;
255
256again:
257 if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
258 return -ENOMEM;
259
260 spin_lock(&dev->object_name_lock);
261 if (obj->name) {
262 args->name = obj->name;
263 spin_unlock(&dev->object_name_lock);
264 return 0;
265 }
266 ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
267 &obj->name);
268 spin_unlock(&dev->object_name_lock);
269 if (ret == -EAGAIN)
270 goto again;
271
272 if (ret != 0) {
273 mutex_lock(&dev->struct_mutex);
274 drm_gem_object_unreference(obj);
275 mutex_unlock(&dev->struct_mutex);
276 return ret;
277 }
278
279
280
281
282
283 args->name = (uint64_t) obj->name;
284
285 return 0;
286}
287
288
289
290
291
292
293
294int
295drm_gem_open_ioctl(struct drm_device *dev, void *data,
296 struct drm_file *file_priv)
297{
298 struct drm_gem_open *args = data;
299 struct drm_gem_object *obj;
300 int ret;
301 int handle;
302
303 if (!(dev->driver->driver_features & DRIVER_GEM))
304 return -ENODEV;
305
306 spin_lock(&dev->object_name_lock);
307 obj = idr_find(&dev->object_name_idr, (int) args->name);
308 if (obj)
309 drm_gem_object_reference(obj);
310 spin_unlock(&dev->object_name_lock);
311 if (!obj)
312 return -ENOENT;
313
314 ret = drm_gem_handle_create(file_priv, obj, &handle);
315 mutex_lock(&dev->struct_mutex);
316 drm_gem_object_unreference(obj);
317 mutex_unlock(&dev->struct_mutex);
318 if (ret)
319 return ret;
320
321 args->handle = handle;
322 args->size = obj->size;
323
324 return 0;
325}
326
327
328
329
330
331void
332drm_gem_open(struct drm_device *dev, struct drm_file *file_private)
333{
334 idr_init(&file_private->object_idr);
335 spin_lock_init(&file_private->table_lock);
336}
337
338
339
340
341
342static int
343drm_gem_object_release_handle(int id, void *ptr, void *data)
344{
345 struct drm_gem_object *obj = ptr;
346
347 drm_gem_object_handle_unreference(obj);
348
349 return 0;
350}
351
352
353
354
355
356
357void
358drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
359{
360 mutex_lock(&dev->struct_mutex);
361 idr_for_each(&file_private->object_idr,
362 &drm_gem_object_release_handle, NULL);
363
364 idr_destroy(&file_private->object_idr);
365 mutex_unlock(&dev->struct_mutex);
366}
367
368
369
370
371
372
373void
374drm_gem_object_free(struct kref *kref)
375{
376 struct drm_gem_object *obj = (struct drm_gem_object *) kref;
377 struct drm_device *dev = obj->dev;
378
379 BUG_ON(!mutex_is_locked(&dev->struct_mutex));
380
381 if (dev->driver->gem_free_object != NULL)
382 dev->driver->gem_free_object(obj);
383
384 fput(obj->filp);
385 atomic_dec(&dev->object_count);
386 atomic_sub(obj->size, &dev->object_memory);
387 kfree(obj);
388}
389EXPORT_SYMBOL(drm_gem_object_free);
390
391
392
393
394
395
396
397
398void
399drm_gem_object_handle_free(struct kref *kref)
400{
401 struct drm_gem_object *obj = container_of(kref,
402 struct drm_gem_object,
403 handlecount);
404 struct drm_device *dev = obj->dev;
405
406
407 spin_lock(&dev->object_name_lock);
408 if (obj->name) {
409 idr_remove(&dev->object_name_idr, obj->name);
410 spin_unlock(&dev->object_name_lock);
411
412
413
414
415 drm_gem_object_unreference(obj);
416 } else
417 spin_unlock(&dev->object_name_lock);
418
419}
420EXPORT_SYMBOL(drm_gem_object_handle_free);
421