Subversion Repositories Kolibri OS

Rev

Rev 4075 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4075 Rev 4569
Line 1... Line 1...
1
/**************************************************************************
1
/**************************************************************************
2
 *
2
 *
3
 * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
3
 * Copyright (c) 2009-2013 VMware, Inc., Palo Alto, CA., USA
4
 * All Rights Reserved.
4
 * All Rights Reserved.
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
8
 * "Software"), to deal in the Software without restriction, including
Line 24... Line 24...
24
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
25
 *
26
 **************************************************************************/
26
 **************************************************************************/
27
/*
27
/*
28
 * Authors: Thomas Hellstrom 
28
 * Authors: Thomas Hellstrom 
-
 
29
 *
-
 
30
 * While no substantial code is shared, the prime code is inspired by
-
 
31
 * drm_prime.c, with
-
 
32
 * Authors:
-
 
33
 *      Dave Airlie 
-
 
34
 *      Rob Clark 
29
 */
35
 */
30
/** @file ttm_ref_object.c
36
/** @file ttm_ref_object.c
31
 *
37
 *
32
 * Base- and reference object implementation for the various
38
 * Base- and reference object implementation for the various
33
 * ttm objects. Implements reference counting, minimal security checks
39
 * ttm objects. Implements reference counting, minimal security checks
34
 * and release on file close.
40
 * and release on file close.
35
 */
41
 */
Line -... Line 42...
-
 
42
 
36
 
43
 
37
/**
44
/**
38
 * struct ttm_object_file
45
 * struct ttm_object_file
39
 *
46
 *
40
 * @tdev: Pointer to the ttm_object_device.
47
 * @tdev: Pointer to the ttm_object_device.
Line 49... Line 56...
49
 * for fast lookup of ref objects given a base object.
56
 * for fast lookup of ref objects given a base object.
50
 */
57
 */
Line 51... Line 58...
51
 
58
 
Line -... Line 59...
-
 
59
#define pr_fmt(fmt) "[TTM] " fmt
-
 
60
 
52
#define pr_fmt(fmt) "[TTM] " fmt
61
#include 
53
 
62
 
54
#include 
63
#include 
55
#include 
64
#include 
56
#include 
65
#include 
Line 67... Line 76...
67
#define pr_err(fmt, ...) \
76
#define pr_err(fmt, ...) \
68
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
77
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
Line 69... Line 78...
69
 
78
 
70
struct ttm_object_file {
79
struct ttm_object_file {
71
	struct ttm_object_device *tdev;
80
	struct ttm_object_device *tdev;
72
	rwlock_t lock;
81
	spinlock_t lock;
73
	struct list_head ref_list;
82
	struct list_head ref_list;
74
	struct drm_open_hash ref_hash[TTM_REF_NUM];
83
	struct drm_open_hash ref_hash[TTM_REF_NUM];
75
	struct kref refcount;
84
	struct kref refcount;
Line 122... Line 131...
122
	enum ttm_ref_type ref_type;
131
	enum ttm_ref_type ref_type;
123
	struct ttm_base_object *obj;
132
	struct ttm_base_object *obj;
124
	struct ttm_object_file *tfile;
133
	struct ttm_object_file *tfile;
125
};
134
};
Line -... Line 135...
-
 
135
 
-
 
136
static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf);
126
 
137
 
127
static inline struct ttm_object_file *
138
static inline struct ttm_object_file *
128
ttm_object_file_ref(struct ttm_object_file *tfile)
139
ttm_object_file_ref(struct ttm_object_file *tfile)
129
{
140
{
130
	kref_get(&tfile->refcount);
141
	kref_get(&tfile->refcount);
Line 204... Line 215...
204
	 * Note: We don't use synchronize_rcu() here because it's far
215
	 * Note: We don't use synchronize_rcu() here because it's far
205
	 * too slow. It's up to the user to free the object using
216
	 * too slow. It's up to the user to free the object using
206
	 * call_rcu() or ttm_base_object_kfree().
217
	 * call_rcu() or ttm_base_object_kfree().
207
	 */
218
	 */
Line 208... Line -...
208
 
-
 
209
	if (base->refcount_release) {
219
 
-
 
220
	ttm_object_file_unref(&base->tfile);
210
		ttm_object_file_unref(&base->tfile);
221
	if (base->refcount_release)
211
		base->refcount_release(&base);
222
		base->refcount_release(&base);
212
	}
-
 
Line 213... Line 223...
213
}
223
}
214
 
224
 
215
void ttm_base_object_unref(struct ttm_base_object **p_base)
225
void ttm_base_object_unref(struct ttm_base_object **p_base)
Line 223... Line 233...
223
EXPORT_SYMBOL(ttm_base_object_unref);
233
EXPORT_SYMBOL(ttm_base_object_unref);
Line 224... Line 234...
224
 
234
 
225
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
235
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
226
					       uint32_t key)
236
					       uint32_t key)
227
{
-
 
228
	struct ttm_object_device *tdev = tfile->tdev;
237
{
229
	struct ttm_base_object *base;
238
	struct ttm_base_object *base = NULL;
-
 
239
	struct drm_hash_item *hash;
230
	struct drm_hash_item *hash;
240
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
Line 231... Line 241...
231
	int ret;
241
	int ret;
232
 
242
 
Line 233... Line 243...
233
//   rcu_read_lock();
243
//	rcu_read_lock();
234
	ret = drm_ht_find_item_rcu(&tdev->object_hash, key, &hash);
244
	ret = drm_ht_find_item_rcu(ht, key, &hash);
235
 
245
 
-
 
246
	if (likely(ret == 0)) {
236
	if (likely(ret == 0)) {
247
		base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
237
		base = drm_hash_entry(hash, struct ttm_base_object, hash);
248
		if (!kref_get_unless_zero(&base->refcount))
Line 238... Line -...
238
		ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL;
-
 
239
	}
249
			base = NULL;
-
 
250
	}
-
 
251
//   rcu_read_unlock();
Line -... Line 252...
-
 
252
 
-
 
253
	return base;
-
 
254
}
240
//   rcu_read_unlock();
255
EXPORT_SYMBOL(ttm_base_object_lookup);
-
 
256
 
-
 
257
struct ttm_base_object *
-
 
258
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
-
 
259
{
-
 
260
	struct ttm_base_object *base = NULL;
-
 
261
	struct drm_hash_item *hash;
-
 
262
	struct drm_open_hash *ht = &tdev->object_hash;
241
 
263
	int ret;
242
	if (unlikely(ret != 0))
264
 
243
		return NULL;
265
	ret = drm_ht_find_item_rcu(ht, key, &hash);
244
 
266
 
Line 245... Line 267...
245
	if (tfile != base->tfile && !base->shareable) {
267
	if (likely(ret == 0)) {
246
		pr_err("Attempted access of non-shareable object\n");
268
		base = drm_hash_entry(hash, struct ttm_base_object, hash);
247
		ttm_base_object_unref(&base);
269
		if (!kref_get_unless_zero(&base->refcount))
Line 248... Line 270...
248
		return NULL;
270
			base = NULL;
249
	}
271
	}
250
 
272
 
251
	return base;
273
	return base;
Line 264... Line 286...
264
 
286
 
265
	if (existed != NULL)
287
	if (existed != NULL)
Line 266... Line 288...
266
		*existed = true;
288
		*existed = true;
267
 
-
 
268
	while (ret == -EINVAL) {
289
 
Line 269... Line 290...
269
		read_lock(&tfile->lock);
290
	while (ret == -EINVAL) {
270
		ret = drm_ht_find_item(ht, base->hash.key, &hash);
291
		ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
271
 
292
 
272
		if (ret == 0) {
-
 
273
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
293
		if (ret == 0) {
274
			kref_get(&ref->kref);
294
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
-
 
295
			if (!kref_get_unless_zero(&ref->kref)) {
Line 275... Line -...
275
			read_unlock(&tfile->lock);
-
 
276
			break;
296
			break;
277
		}
297
		}
278
 
298
		}
279
		read_unlock(&tfile->lock);
299
 
280
		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
300
		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
Line 291... Line 311...
291
		ref->obj = base;
311
		ref->obj = base;
292
		ref->tfile = tfile;
312
		ref->tfile = tfile;
293
		ref->ref_type = ref_type;
313
		ref->ref_type = ref_type;
294
		kref_init(&ref->kref);
314
		kref_init(&ref->kref);
Line 295... Line 315...
295
 
315
 
296
		write_lock(&tfile->lock);
316
		spin_lock(&tfile->lock);
Line 297... Line 317...
297
		ret = drm_ht_insert_item(ht, &ref->hash);
317
		ret = drm_ht_insert_item_rcu(ht, &ref->hash);
298
 
318
 
299
		if (likely(ret == 0)) {
319
		if (likely(ret == 0)) {
300
			list_add_tail(&ref->head, &tfile->ref_list);
320
			list_add_tail(&ref->head, &tfile->ref_list);
301
			kref_get(&base->refcount);
321
			kref_get(&base->refcount);
302
			write_unlock(&tfile->lock);
322
			spin_unlock(&tfile->lock);
303
			if (existed != NULL)
323
			if (existed != NULL)
304
				*existed = false;
324
				*existed = false;
Line 305... Line 325...
305
			break;
325
			break;
306
		}
326
		}
Line 307... Line 327...
307
 
327
 
308
		write_unlock(&tfile->lock);
328
		spin_unlock(&tfile->lock);
309
		BUG_ON(ret != -EINVAL);
329
		BUG_ON(ret != -EINVAL);
Line 324... Line 344...
324
	struct ttm_object_file *tfile = ref->tfile;
344
	struct ttm_object_file *tfile = ref->tfile;
325
	struct drm_open_hash *ht;
345
	struct drm_open_hash *ht;
326
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
346
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
Line 327... Line 347...
327
 
347
 
328
	ht = &tfile->ref_hash[ref->ref_type];
348
	ht = &tfile->ref_hash[ref->ref_type];
329
	(void)drm_ht_remove_item(ht, &ref->hash);
349
	(void)drm_ht_remove_item_rcu(ht, &ref->hash);
330
	list_del(&ref->head);
350
	list_del(&ref->head);
Line 331... Line 351...
331
	write_unlock(&tfile->lock);
351
	spin_unlock(&tfile->lock);
332
 
352
 
Line 333... Line 353...
333
	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
353
	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
334
		base->ref_obj_release(base, ref->ref_type);
354
		base->ref_obj_release(base, ref->ref_type);
335
 
355
 
336
	ttm_base_object_unref(&ref->obj);
356
	ttm_base_object_unref(&ref->obj);
337
	ttm_mem_global_free(mem_glob, sizeof(*ref));
357
	ttm_mem_global_free(mem_glob, sizeof(*ref));
Line 338... Line 358...
338
	kfree(ref);
358
	kfree(ref);
339
	write_lock(&tfile->lock);
359
	spin_lock(&tfile->lock);
340
}
360
}
341
 
361
 
342
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
362
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
343
			      unsigned long key, enum ttm_ref_type ref_type)
363
			      unsigned long key, enum ttm_ref_type ref_type)
344
{
364
{
Line 345... Line 365...
345
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
365
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
346
	struct ttm_ref_object *ref;
366
	struct ttm_ref_object *ref;
347
	struct drm_hash_item *hash;
367
	struct drm_hash_item *hash;
348
	int ret;
368
	int ret;
349
 
369
 
350
	write_lock(&tfile->lock);
370
	spin_lock(&tfile->lock);
351
	ret = drm_ht_find_item(ht, key, &hash);
371
	ret = drm_ht_find_item(ht, key, &hash);
352
	if (unlikely(ret != 0)) {
372
	if (unlikely(ret != 0)) {
353
		write_unlock(&tfile->lock);
373
		spin_unlock(&tfile->lock);
354
		return -EINVAL;
374
		return -EINVAL;
355
	}
375
	}
356
	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
376
	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
Line 357... Line 377...
357
	kref_put(&ref->kref, ttm_ref_object_release);
377
	kref_put(&ref->kref, ttm_ref_object_release);
Line 366... Line 386...
366
	struct list_head *list;
386
	struct list_head *list;
367
	unsigned int i;
387
	unsigned int i;
368
	struct ttm_object_file *tfile = *p_tfile;
388
	struct ttm_object_file *tfile = *p_tfile;
Line 369... Line 389...
369
 
389
 
370
	*p_tfile = NULL;
390
	*p_tfile = NULL;
Line 371... Line 391...
371
	write_lock(&tfile->lock);
391
	spin_lock(&tfile->lock);
372
 
392
 
373
	/*
393
	/*
374
	 * Since we release the lock within the loop, we have to
394
	 * Since we release the lock within the loop, we have to
Line 382... Line 402...
382
	}
402
	}
Line 383... Line 403...
383
 
403
 
384
	for (i = 0; i < TTM_REF_NUM; ++i)
404
	for (i = 0; i < TTM_REF_NUM; ++i)
Line 385... Line 405...
385
		drm_ht_remove(&tfile->ref_hash[i]);
405
		drm_ht_remove(&tfile->ref_hash[i]);
386
 
406
 
387
	write_unlock(&tfile->lock);
407
	spin_unlock(&tfile->lock);
388
	ttm_object_file_unref(&tfile);
408
	ttm_object_file_unref(&tfile);
Line 389... Line 409...
389
}
409
}
Line 398... Line 418...
398
	int ret;
418
	int ret;
Line 399... Line 419...
399
 
419
 
400
	if (unlikely(tfile == NULL))
420
	if (unlikely(tfile == NULL))
Line 401... Line 421...
401
		return NULL;
421
		return NULL;
402
 
422
 
403
	rwlock_init(&tfile->lock);
423
	spin_lock_init(&tfile->lock);
404
	tfile->tdev = tdev;
424
	tfile->tdev = tdev;
Line 405... Line 425...
405
	kref_init(&tfile->refcount);
425
	kref_init(&tfile->refcount);
Line 422... Line 442...
422
 
442
 
423
	return NULL;
443
	return NULL;
424
}
444
}
Line 425... Line 445...
425
EXPORT_SYMBOL(ttm_object_file_init);
445
EXPORT_SYMBOL(ttm_object_file_init);
426
 
446
 
427
struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global
447
struct ttm_object_device *
-
 
448
ttm_object_device_init(struct ttm_mem_global *mem_glob,
428
						 *mem_glob,
449
		       unsigned int hash_order,
429
						 unsigned int hash_order)
450
		       const struct dma_buf_ops *ops)
430
{
451
{
Line 431... Line 452...
431
	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
452
	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
Line 436... Line 457...
436
 
457
 
437
	tdev->mem_glob = mem_glob;
458
	tdev->mem_glob = mem_glob;
438
	spin_lock_init(&tdev->object_lock);
459
	spin_lock_init(&tdev->object_lock);
439
	atomic_set(&tdev->object_count, 0);
460
	atomic_set(&tdev->object_count, 0);
-
 
461
	ret = drm_ht_create(&tdev->object_hash, hash_order);
-
 
462
	if (ret != 0)
Line 440... Line 463...
440
	ret = drm_ht_create(&tdev->object_hash, hash_order);
463
		goto out_no_object_hash;
-
 
464
 
-
 
465
//   tdev->ops = *ops;
-
 
466
//   tdev->dmabuf_release = tdev->ops.release;
-
 
467
//   tdev->ops.release = ttm_prime_dmabuf_release;
441
 
468
//   tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) +
Line -... Line 469...
-
 
469
//       ttm_round_pot(sizeof(struct file));
442
	if (likely(ret == 0))
470
		return tdev;
443
		return tdev;
471
 
444
 
472
out_no_object_hash:
445
	kfree(tdev);
473
	kfree(tdev);