Subversion Repositories Kolibri OS

Rev

Rev 4569 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4569 Rev 6296
Line 56... Line 56...
56
 * for fast lookup of ref objects given a base object.
56
 * for fast lookup of ref objects given a base object.
57
 */
57
 */
Line 58... Line 58...
58
 
58
 
Line 59... Line -...
59
#define pr_fmt(fmt) "[TTM] " fmt
-
 
60
 
-
 
61
#include 
59
#define pr_fmt(fmt) "[TTM] " fmt
62
 
60
 
63
#include 
61
#include 
64
#include 
62
#include 
65
#include 
63
#include 
66
#include 
64
#include 
67
#include 
65
#include 
68
#include 
-
 
69
//#include 
-
 
70
 
-
 
71
static inline int __must_check kref_get_unless_zero(struct kref *kref)
-
 
72
{
-
 
73
    return atomic_add_unless(&kref->refcount, 1, 0);
-
 
74
}
-
 
75
 
-
 
Line 76... Line 66...
76
#define pr_err(fmt, ...) \
66
#include 
77
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
67
#include 
78
 
68
 
79
struct ttm_object_file {
69
struct ttm_object_file {
Line 99... Line 89...
99
struct ttm_object_device {
89
struct ttm_object_device {
100
	spinlock_t object_lock;
90
	spinlock_t object_lock;
101
	struct drm_open_hash object_hash;
91
	struct drm_open_hash object_hash;
102
	atomic_t object_count;
92
	atomic_t object_count;
103
	struct ttm_mem_global *mem_glob;
93
	struct ttm_mem_global *mem_glob;
-
 
94
	struct dma_buf_ops ops;
-
 
95
	void (*dmabuf_release)(struct dma_buf *dma_buf);
-
 
96
	size_t dma_buf_size;
104
};
97
};
Line 105... Line 98...
105
 
98
 
106
/**
99
/**
107
 * struct ttm_ref_object
100
 * struct ttm_ref_object
Line 123... Line 116...
123
 * multiple ref objects if a ttm_object_file references the same base
116
 * multiple ref objects if a ttm_object_file references the same base
124
 * object more than once.
117
 * object more than once.
125
 */
118
 */
Line 126... Line 119...
126
 
119
 
-
 
120
struct ttm_ref_object {
127
struct ttm_ref_object {
121
	struct rcu_head rcu_head;
128
	struct drm_hash_item hash;
122
	struct drm_hash_item hash;
129
	struct list_head head;
123
	struct list_head head;
130
	struct kref kref;
124
	struct kref kref;
131
	enum ttm_ref_type ref_type;
125
	enum ttm_ref_type ref_type;
Line 238... Line 232...
238
	struct ttm_base_object *base = NULL;
232
	struct ttm_base_object *base = NULL;
239
	struct drm_hash_item *hash;
233
	struct drm_hash_item *hash;
240
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
234
	struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
241
	int ret;
235
	int ret;
Line 242... Line 236...
242
 
236
 
243
//	rcu_read_lock();
237
	rcu_read_lock();
Line 244... Line 238...
244
	ret = drm_ht_find_item_rcu(ht, key, &hash);
238
	ret = drm_ht_find_item_rcu(ht, key, &hash);
245
 
239
 
246
	if (likely(ret == 0)) {
240
	if (likely(ret == 0)) {
247
		base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
241
		base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
248
		if (!kref_get_unless_zero(&base->refcount))
242
		if (!kref_get_unless_zero(&base->refcount))
249
			base = NULL;
243
			base = NULL;
Line 250... Line 244...
250
	}
244
	}
251
//   rcu_read_unlock();
245
	rcu_read_unlock();
252
 
246
 
Line 260... Line 254...
260
	struct ttm_base_object *base = NULL;
254
	struct ttm_base_object *base = NULL;
261
	struct drm_hash_item *hash;
255
	struct drm_hash_item *hash;
262
	struct drm_open_hash *ht = &tdev->object_hash;
256
	struct drm_open_hash *ht = &tdev->object_hash;
263
	int ret;
257
	int ret;
Line -... Line 258...
-
 
258
 
264
 
259
	rcu_read_lock();
Line 265... Line 260...
265
	ret = drm_ht_find_item_rcu(ht, key, &hash);
260
	ret = drm_ht_find_item_rcu(ht, key, &hash);
266
 
261
 
267
	if (likely(ret == 0)) {
262
	if (likely(ret == 0)) {
268
		base = drm_hash_entry(hash, struct ttm_base_object, hash);
263
		base = drm_hash_entry(hash, struct ttm_base_object, hash);
269
		if (!kref_get_unless_zero(&base->refcount))
264
		if (!kref_get_unless_zero(&base->refcount))
-
 
265
			base = NULL;
Line 270... Line 266...
270
			base = NULL;
266
	}
271
	}
267
	rcu_read_unlock();
272
 
268
 
Line 286... Line 282...
286
 
282
 
287
	if (existed != NULL)
283
	if (existed != NULL)
Line 288... Line 284...
288
		*existed = true;
284
		*existed = true;
-
 
285
 
289
 
286
	while (ret == -EINVAL) {
Line 290... Line 287...
290
	while (ret == -EINVAL) {
287
		rcu_read_lock();
291
		ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
288
		ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
292
 
289
 
-
 
290
		if (ret == 0) {
293
		if (ret == 0) {
291
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
294
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
292
			if (kref_get_unless_zero(&ref->kref)) {
295
			if (!kref_get_unless_zero(&ref->kref)) {
293
				rcu_read_unlock();
Line -... Line 294...
-
 
294
				break;
296
			break;
295
			}
297
		}
296
		}
298
		}
297
 
299
 
298
		rcu_read_unlock();
300
		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
299
		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
Line 353... Line 352...
353
	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
352
	if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release)
354
		base->ref_obj_release(base, ref->ref_type);
353
		base->ref_obj_release(base, ref->ref_type);
Line 355... Line 354...
355
 
354
 
356
	ttm_base_object_unref(&ref->obj);
355
	ttm_base_object_unref(&ref->obj);
357
	ttm_mem_global_free(mem_glob, sizeof(*ref));
356
	ttm_mem_global_free(mem_glob, sizeof(*ref));
358
	kfree(ref);
357
	kfree_rcu(ref, rcu_head);
359
	spin_lock(&tfile->lock);
358
	spin_lock(&tfile->lock);
Line 360... Line 359...
360
}
359
}
361
 
360
 
Line 460... Line 459...
460
	atomic_set(&tdev->object_count, 0);
459
	atomic_set(&tdev->object_count, 0);
461
	ret = drm_ht_create(&tdev->object_hash, hash_order);
460
	ret = drm_ht_create(&tdev->object_hash, hash_order);
462
	if (ret != 0)
461
	if (ret != 0)
463
		goto out_no_object_hash;
462
		goto out_no_object_hash;
Line 464... Line 463...
464
 
463
 
465
//   tdev->ops = *ops;
464
	tdev->ops = *ops;
466
//   tdev->dmabuf_release = tdev->ops.release;
465
	tdev->dmabuf_release = tdev->ops.release;
467
//   tdev->ops.release = ttm_prime_dmabuf_release;
466
	tdev->ops.release = ttm_prime_dmabuf_release;
468
//   tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) +
467
	tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) +
469
//       ttm_round_pot(sizeof(struct file));
468
		ttm_round_pot(sizeof(struct file));
Line 470... Line 469...
470
		return tdev;
469
	return tdev;
471
 
470
 
472
out_no_object_hash:
471
out_no_object_hash:
Line 486... Line 485...
486
	spin_unlock(&tdev->object_lock);
485
	spin_unlock(&tdev->object_lock);
Line 487... Line 486...
487
 
486
 
488
	kfree(tdev);
487
	kfree(tdev);
489
}
488
}
-
 
489
EXPORT_SYMBOL(ttm_object_device_release);
-
 
490
 
-
 
491
/**
-
 
492
 * get_dma_buf_unless_doomed - get a dma_buf reference if possible.
-
 
493
 *
-
 
494
 * @dma_buf: Non-refcounted pointer to a struct dma-buf.
-
 
495
 *
-
 
496
 * Obtain a file reference from a lookup structure that doesn't refcount
-
 
497
 * the file, but synchronizes with its release method to make sure it has
-
 
498
 * not been freed yet. See for example kref_get_unless_zero documentation.
-
 
499
 * Returns true if refcounting succeeds, false otherwise.
-
 
500
 *
-
 
501
 * Nobody really wants this as a public API yet, so let it mature here
-
 
502
 * for some time...
-
 
503
 */
-
 
504
static bool __must_check get_dma_buf_unless_doomed(struct dma_buf *dmabuf)
-
 
505
{
-
 
506
	return atomic_long_inc_not_zero(&dmabuf->file->f_count) != 0L;
-
 
507
}
-
 
508
 
-
 
509
/**
-
 
510
 * ttm_prime_refcount_release - refcount release method for a prime object.
-
 
511
 *
-
 
512
 * @p_base: Pointer to ttm_base_object pointer.
-
 
513
 *
-
 
514
 * This is a wrapper that calls the refcount_release founction of the
-
 
515
 * underlying object. At the same time it cleans up the prime object.
-
 
516
 * This function is called when all references to the base object we
-
 
517
 * derive from are gone.
-
 
518
 */
-
 
519
static void ttm_prime_refcount_release(struct ttm_base_object **p_base)
-
 
520
{
-
 
521
	struct ttm_base_object *base = *p_base;
-
 
522
	struct ttm_prime_object *prime;
-
 
523
 
-
 
524
	*p_base = NULL;
-
 
525
	prime = container_of(base, struct ttm_prime_object, base);
-
 
526
	BUG_ON(prime->dma_buf != NULL);
-
 
527
	mutex_destroy(&prime->mutex);
-
 
528
	if (prime->refcount_release)
-
 
529
		prime->refcount_release(&base);
-
 
530
}
-
 
531
 
-
 
532
/**
-
 
533
 * ttm_prime_dmabuf_release - Release method for the dma-bufs we export
-
 
534
 *
-
 
535
 * @dma_buf:
-
 
536
 *
-
 
537
 * This function first calls the dma_buf release method the driver
-
 
538
 * provides. Then it cleans up our dma_buf pointer used for lookup,
-
 
539
 * and finally releases the reference the dma_buf has on our base
-
 
540
 * object.
-
 
541
 */
-
 
542
static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf)
-
 
543
{
-
 
544
	struct ttm_prime_object *prime =
-
 
545
		(struct ttm_prime_object *) dma_buf->priv;
-
 
546
	struct ttm_base_object *base = &prime->base;
-
 
547
	struct ttm_object_device *tdev = base->tfile->tdev;
-
 
548
 
-
 
549
	if (tdev->dmabuf_release)
-
 
550
		tdev->dmabuf_release(dma_buf);
-
 
551
	mutex_lock(&prime->mutex);
-
 
552
	if (prime->dma_buf == dma_buf)
-
 
553
		prime->dma_buf = NULL;
-
 
554
	mutex_unlock(&prime->mutex);
-
 
555
	ttm_mem_global_free(tdev->mem_glob, tdev->dma_buf_size);
-
 
556
	ttm_base_object_unref(&base);
-
 
557
}
-
 
558
 
-
 
559
/**
-
 
560
 * ttm_prime_fd_to_handle - Get a base object handle from a prime fd
-
 
561
 *
-
 
562
 * @tfile: A struct ttm_object_file identifying the caller.
-
 
563
 * @fd: The prime / dmabuf fd.
-
 
564
 * @handle: The returned handle.
-
 
565
 *
-
 
566
 * This function returns a handle to an object that previously exported
-
 
567
 * a dma-buf. Note that we don't handle imports yet, because we simply
-
 
568
 * have no consumers of that implementation.
-
 
569
 */
-
 
570
int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
-
 
571
			   int fd, u32 *handle)
-
 
572
{
-
 
573
	struct ttm_object_device *tdev = tfile->tdev;
-
 
574
	struct dma_buf *dma_buf;
-
 
575
	struct ttm_prime_object *prime;
-
 
576
	struct ttm_base_object *base;
-
 
577
	int ret;
-
 
578
 
-
 
579
	dma_buf = dma_buf_get(fd);
-
 
580
	if (IS_ERR(dma_buf))
-
 
581
		return PTR_ERR(dma_buf);
-
 
582
 
-
 
583
	if (dma_buf->ops != &tdev->ops)
-
 
584
		return -ENOSYS;
-
 
585
 
-
 
586
	prime = (struct ttm_prime_object *) dma_buf->priv;
-
 
587
	base = &prime->base;
-
 
588
	*handle = base->hash.key;
-
 
589
	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
-
 
590
 
-
 
591
	dma_buf_put(dma_buf);
-
 
592
 
-
 
593
	return ret;
-
 
594
}
-
 
595
EXPORT_SYMBOL_GPL(ttm_prime_fd_to_handle);
-
 
596
 
-
 
597
/**
-
 
598
 * ttm_prime_handle_to_fd - Return a dma_buf fd from a ttm prime object
-
 
599
 *
-
 
600
 * @tfile: Struct ttm_object_file identifying the caller.
-
 
601
 * @handle: Handle to the object we're exporting from.
-
 
602
 * @flags: flags for dma-buf creation. We just pass them on.
-
 
603
 * @prime_fd: The returned file descriptor.
-
 
604
 *
-
 
605
 */
-
 
606
int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
-
 
607
			   uint32_t handle, uint32_t flags,
-
 
608
			   int *prime_fd)
-
 
609
{
-
 
610
	struct ttm_object_device *tdev = tfile->tdev;
-
 
611
	struct ttm_base_object *base;
-
 
612
	struct dma_buf *dma_buf;
-
 
613
	struct ttm_prime_object *prime;
-
 
614
	int ret;
-
 
615
 
-
 
616
	base = ttm_base_object_lookup(tfile, handle);
-
 
617
	if (unlikely(base == NULL ||
-
 
618
		     base->object_type != ttm_prime_type)) {
-
 
619
		ret = -ENOENT;
-
 
620
		goto out_unref;
-
 
621
	}
-
 
622
 
-
 
623
	prime = container_of(base, struct ttm_prime_object, base);
-
 
624
	if (unlikely(!base->shareable)) {
-
 
625
		ret = -EPERM;
-
 
626
		goto out_unref;
-
 
627
	}
-
 
628
 
-
 
629
	ret = mutex_lock_interruptible(&prime->mutex);
-
 
630
	if (unlikely(ret != 0)) {
-
 
631
		ret = -ERESTARTSYS;
-
 
632
		goto out_unref;
-
 
633
	}
-
 
634
 
-
 
635
	dma_buf = prime->dma_buf;
-
 
636
	if (!dma_buf || !get_dma_buf_unless_doomed(dma_buf)) {
-
 
637
		DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-
 
638
 
-
 
639
		exp_info.ops = &tdev->ops;
-
 
640
		exp_info.size = prime->size;
-
 
641
		exp_info.flags = flags;
-
 
642
		exp_info.priv = prime;
-
 
643
 
-
 
644
		/*
-
 
645
		 * Need to create a new dma_buf, with memory accounting.
-
 
646
		 */
-
 
647
		ret = ttm_mem_global_alloc(tdev->mem_glob, tdev->dma_buf_size,
-
 
648
					   false, true);
-
 
649
		if (unlikely(ret != 0)) {
-
 
650
			mutex_unlock(&prime->mutex);
-
 
651
			goto out_unref;
-
 
652
		}
-
 
653
 
-
 
654
		dma_buf = dma_buf_export(&exp_info);
-
 
655
		if (IS_ERR(dma_buf)) {
-
 
656
			ret = PTR_ERR(dma_buf);
-
 
657
			ttm_mem_global_free(tdev->mem_glob,
-
 
658
					    tdev->dma_buf_size);
-
 
659
			mutex_unlock(&prime->mutex);
-
 
660
			goto out_unref;
-
 
661
		}
-
 
662
 
-
 
663
		/*
-
 
664
		 * dma_buf has taken the base object reference
-
 
665
		 */
-
 
666
		base = NULL;
-
 
667
		prime->dma_buf = dma_buf;
-
 
668
	}
-
 
669
	mutex_unlock(&prime->mutex);
-
 
670
 
-
 
671
	ret = dma_buf_fd(dma_buf, flags);
-
 
672
	if (ret >= 0) {
-
 
673
		*prime_fd = ret;
-
 
674
		ret = 0;
-
 
675
	} else
-
 
676
		dma_buf_put(dma_buf);
-
 
677
 
-
 
678
out_unref:
-
 
679
	if (base)
-
 
680
		ttm_base_object_unref(&base);
-
 
681
	return ret;
-
 
682
}
-
 
683
EXPORT_SYMBOL_GPL(ttm_prime_handle_to_fd);
-
 
684
 
-
 
685
/**
-
 
686
 * ttm_prime_object_init - Initialize a ttm_prime_object
-
 
687
 *
-
 
688
 * @tfile: struct ttm_object_file identifying the caller
-
 
689
 * @size: The size of the dma_bufs we export.
-
 
690
 * @prime: The object to be initialized.
-
 
691
 * @shareable: See ttm_base_object_init
-
 
692
 * @type: See ttm_base_object_init
-
 
693
 * @refcount_release: See ttm_base_object_init
-
 
694
 * @ref_obj_release: See ttm_base_object_init
-
 
695
 *
-
 
696
 * Initializes an object which is compatible with the drm_prime model
-
 
697
 * for data sharing between processes and devices.
-
 
698
 */
-
 
699
int ttm_prime_object_init(struct ttm_object_file *tfile, size_t size,
-
 
700
			  struct ttm_prime_object *prime, bool shareable,
-
 
701
			  enum ttm_object_type type,
-
 
702
			  void (*refcount_release) (struct ttm_base_object **),
-
 
703
			  void (*ref_obj_release) (struct ttm_base_object *,
-
 
704
						   enum ttm_ref_type ref_type))
-
 
705
{
-
 
706
	mutex_init(&prime->mutex);
-
 
707
	prime->size = PAGE_ALIGN(size);
-
 
708
	prime->real_type = type;
-
 
709
	prime->dma_buf = NULL;
-
 
710
	prime->refcount_release = refcount_release;
-
 
711
	return ttm_base_object_init(tfile, &prime->base, shareable,
-
 
712
				    ttm_prime_type,
-
 
713
				    ttm_prime_refcount_release,
-
 
714
				    ref_obj_release);
-
 
715
}