Subversion Repositories Kolibri OS

Rev

Rev 4569 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4569 Rev 6296
1
/**************************************************************************
1
/**************************************************************************
2
 *
2
 *
3
 * Copyright (c) 2009-2013 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
9
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
12
 * the following conditions:
13
 *
13
 *
14
 * The above copyright notice and this permission notice (including the
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
16
 * of the Software.
17
 *
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
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
 *
29
 *
30
 * While no substantial code is shared, the prime code is inspired by
30
 * While no substantial code is shared, the prime code is inspired by
31
 * drm_prime.c, with
31
 * drm_prime.c, with
32
 * Authors:
32
 * Authors:
33
 *      Dave Airlie 
33
 *      Dave Airlie 
34
 *      Rob Clark 
34
 *      Rob Clark 
35
 */
35
 */
36
/** @file ttm_ref_object.c
36
/** @file ttm_ref_object.c
37
 *
37
 *
38
 * Base- and reference object implementation for the various
38
 * Base- and reference object implementation for the various
39
 * ttm objects. Implements reference counting, minimal security checks
39
 * ttm objects. Implements reference counting, minimal security checks
40
 * and release on file close.
40
 * and release on file close.
41
 */
41
 */
42
 
42
 
43
 
43
 
44
/**
44
/**
45
 * struct ttm_object_file
45
 * struct ttm_object_file
46
 *
46
 *
47
 * @tdev: Pointer to the ttm_object_device.
47
 * @tdev: Pointer to the ttm_object_device.
48
 *
48
 *
49
 * @lock: Lock that protects the ref_list list and the
49
 * @lock: Lock that protects the ref_list list and the
50
 * ref_hash hash tables.
50
 * ref_hash hash tables.
51
 *
51
 *
52
 * @ref_list: List of ttm_ref_objects to be destroyed at
52
 * @ref_list: List of ttm_ref_objects to be destroyed at
53
 * file release.
53
 * file release.
54
 *
54
 *
55
 * @ref_hash: Hash tables of ref objects, one per ttm_ref_type,
55
 * @ref_hash: Hash tables of ref objects, one per ttm_ref_type,
56
 * for fast lookup of ref objects given a base object.
56
 * for fast lookup of ref objects given a base object.
57
 */
57
 */
58
 
58
 
59
#define pr_fmt(fmt) "[TTM] " fmt
59
#define pr_fmt(fmt) "[TTM] " fmt
60
 
-
 
61
#include 
-
 
62
 
60
 
63
#include 
61
#include 
64
#include 
62
#include 
65
#include 
63
#include 
66
#include 
64
#include 
67
#include 
65
#include 
68
#include 
66
#include 
69
//#include 
67
#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
 
-
 
76
#define pr_err(fmt, ...) \
-
 
77
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-
 
78
 
68
 
79
struct ttm_object_file {
69
struct ttm_object_file {
80
	struct ttm_object_device *tdev;
70
	struct ttm_object_device *tdev;
81
	spinlock_t lock;
71
	spinlock_t lock;
82
	struct list_head ref_list;
72
	struct list_head ref_list;
83
	struct drm_open_hash ref_hash[TTM_REF_NUM];
73
	struct drm_open_hash ref_hash[TTM_REF_NUM];
84
	struct kref refcount;
74
	struct kref refcount;
85
};
75
};
86
 
76
 
87
/**
77
/**
88
 * struct ttm_object_device
78
 * struct ttm_object_device
89
 *
79
 *
90
 * @object_lock: lock that protects the object_hash hash table.
80
 * @object_lock: lock that protects the object_hash hash table.
91
 *
81
 *
92
 * @object_hash: hash table for fast lookup of object global names.
82
 * @object_hash: hash table for fast lookup of object global names.
93
 *
83
 *
94
 * @object_count: Per device object count.
84
 * @object_count: Per device object count.
95
 *
85
 *
96
 * This is the per-device data structure needed for ttm object management.
86
 * This is the per-device data structure needed for ttm object management.
97
 */
87
 */
98
 
88
 
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
};
105
 
98
 
106
/**
99
/**
107
 * struct ttm_ref_object
100
 * struct ttm_ref_object
108
 *
101
 *
109
 * @hash: Hash entry for the per-file object reference hash.
102
 * @hash: Hash entry for the per-file object reference hash.
110
 *
103
 *
111
 * @head: List entry for the per-file list of ref-objects.
104
 * @head: List entry for the per-file list of ref-objects.
112
 *
105
 *
113
 * @kref: Ref count.
106
 * @kref: Ref count.
114
 *
107
 *
115
 * @obj: Base object this ref object is referencing.
108
 * @obj: Base object this ref object is referencing.
116
 *
109
 *
117
 * @ref_type: Type of ref object.
110
 * @ref_type: Type of ref object.
118
 *
111
 *
119
 * This is similar to an idr object, but it also has a hash table entry
112
 * This is similar to an idr object, but it also has a hash table entry
120
 * that allows lookup with a pointer to the referenced object as a key. In
113
 * that allows lookup with a pointer to the referenced object as a key. In
121
 * that way, one can easily detect whether a base object is referenced by
114
 * that way, one can easily detect whether a base object is referenced by
122
 * a particular ttm_object_file. It also carries a ref count to avoid creating
115
 * a particular ttm_object_file. It also carries a ref count to avoid creating
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
 */
126
 
119
 
127
struct ttm_ref_object {
120
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;
132
	struct ttm_base_object *obj;
126
	struct ttm_base_object *obj;
133
	struct ttm_object_file *tfile;
127
	struct ttm_object_file *tfile;
134
};
128
};
135
 
129
 
136
static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf);
130
static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf);
137
 
131
 
138
static inline struct ttm_object_file *
132
static inline struct ttm_object_file *
139
ttm_object_file_ref(struct ttm_object_file *tfile)
133
ttm_object_file_ref(struct ttm_object_file *tfile)
140
{
134
{
141
	kref_get(&tfile->refcount);
135
	kref_get(&tfile->refcount);
142
	return tfile;
136
	return tfile;
143
}
137
}
144
 
138
 
145
static void ttm_object_file_destroy(struct kref *kref)
139
static void ttm_object_file_destroy(struct kref *kref)
146
{
140
{
147
	struct ttm_object_file *tfile =
141
	struct ttm_object_file *tfile =
148
		container_of(kref, struct ttm_object_file, refcount);
142
		container_of(kref, struct ttm_object_file, refcount);
149
 
143
 
150
	kfree(tfile);
144
	kfree(tfile);
151
}
145
}
152
 
146
 
153
 
147
 
154
static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile)
148
static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile)
155
{
149
{
156
	struct ttm_object_file *tfile = *p_tfile;
150
	struct ttm_object_file *tfile = *p_tfile;
157
 
151
 
158
	*p_tfile = NULL;
152
	*p_tfile = NULL;
159
	kref_put(&tfile->refcount, ttm_object_file_destroy);
153
	kref_put(&tfile->refcount, ttm_object_file_destroy);
160
}
154
}
161
 
155
 
162
 
156
 
163
int ttm_base_object_init(struct ttm_object_file *tfile,
157
int ttm_base_object_init(struct ttm_object_file *tfile,
164
			 struct ttm_base_object *base,
158
			 struct ttm_base_object *base,
165
			 bool shareable,
159
			 bool shareable,
166
			 enum ttm_object_type object_type,
160
			 enum ttm_object_type object_type,
167
			 void (*refcount_release) (struct ttm_base_object **),
161
			 void (*refcount_release) (struct ttm_base_object **),
168
			 void (*ref_obj_release) (struct ttm_base_object *,
162
			 void (*ref_obj_release) (struct ttm_base_object *,
169
						  enum ttm_ref_type ref_type))
163
						  enum ttm_ref_type ref_type))
170
{
164
{
171
	struct ttm_object_device *tdev = tfile->tdev;
165
	struct ttm_object_device *tdev = tfile->tdev;
172
	int ret;
166
	int ret;
173
 
167
 
174
	base->shareable = shareable;
168
	base->shareable = shareable;
175
	base->tfile = ttm_object_file_ref(tfile);
169
	base->tfile = ttm_object_file_ref(tfile);
176
	base->refcount_release = refcount_release;
170
	base->refcount_release = refcount_release;
177
	base->ref_obj_release = ref_obj_release;
171
	base->ref_obj_release = ref_obj_release;
178
	base->object_type = object_type;
172
	base->object_type = object_type;
179
	kref_init(&base->refcount);
173
	kref_init(&base->refcount);
180
	spin_lock(&tdev->object_lock);
174
	spin_lock(&tdev->object_lock);
181
	ret = drm_ht_just_insert_please_rcu(&tdev->object_hash,
175
	ret = drm_ht_just_insert_please_rcu(&tdev->object_hash,
182
					    &base->hash,
176
					    &base->hash,
183
					    (unsigned long)base, 31, 0, 0);
177
					    (unsigned long)base, 31, 0, 0);
184
	spin_unlock(&tdev->object_lock);
178
	spin_unlock(&tdev->object_lock);
185
	if (unlikely(ret != 0))
179
	if (unlikely(ret != 0))
186
		goto out_err0;
180
		goto out_err0;
187
 
181
 
188
	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
182
	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
189
	if (unlikely(ret != 0))
183
	if (unlikely(ret != 0))
190
		goto out_err1;
184
		goto out_err1;
191
 
185
 
192
	ttm_base_object_unref(&base);
186
	ttm_base_object_unref(&base);
193
 
187
 
194
	return 0;
188
	return 0;
195
out_err1:
189
out_err1:
196
	spin_lock(&tdev->object_lock);
190
	spin_lock(&tdev->object_lock);
197
	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
191
	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
198
	spin_unlock(&tdev->object_lock);
192
	spin_unlock(&tdev->object_lock);
199
out_err0:
193
out_err0:
200
	return ret;
194
	return ret;
201
}
195
}
202
EXPORT_SYMBOL(ttm_base_object_init);
196
EXPORT_SYMBOL(ttm_base_object_init);
203
 
197
 
204
static void ttm_release_base(struct kref *kref)
198
static void ttm_release_base(struct kref *kref)
205
{
199
{
206
	struct ttm_base_object *base =
200
	struct ttm_base_object *base =
207
	    container_of(kref, struct ttm_base_object, refcount);
201
	    container_of(kref, struct ttm_base_object, refcount);
208
	struct ttm_object_device *tdev = base->tfile->tdev;
202
	struct ttm_object_device *tdev = base->tfile->tdev;
209
 
203
 
210
	spin_lock(&tdev->object_lock);
204
	spin_lock(&tdev->object_lock);
211
	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
205
	(void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
212
	spin_unlock(&tdev->object_lock);
206
	spin_unlock(&tdev->object_lock);
213
 
207
 
214
	/*
208
	/*
215
	 * Note: We don't use synchronize_rcu() here because it's far
209
	 * Note: We don't use synchronize_rcu() here because it's far
216
	 * too slow. It's up to the user to free the object using
210
	 * too slow. It's up to the user to free the object using
217
	 * call_rcu() or ttm_base_object_kfree().
211
	 * call_rcu() or ttm_base_object_kfree().
218
	 */
212
	 */
219
 
213
 
220
	ttm_object_file_unref(&base->tfile);
214
	ttm_object_file_unref(&base->tfile);
221
	if (base->refcount_release)
215
	if (base->refcount_release)
222
		base->refcount_release(&base);
216
		base->refcount_release(&base);
223
}
217
}
224
 
218
 
225
void ttm_base_object_unref(struct ttm_base_object **p_base)
219
void ttm_base_object_unref(struct ttm_base_object **p_base)
226
{
220
{
227
	struct ttm_base_object *base = *p_base;
221
	struct ttm_base_object *base = *p_base;
228
 
222
 
229
	*p_base = NULL;
223
	*p_base = NULL;
230
 
224
 
231
	kref_put(&base->refcount, ttm_release_base);
225
	kref_put(&base->refcount, ttm_release_base);
232
}
226
}
233
EXPORT_SYMBOL(ttm_base_object_unref);
227
EXPORT_SYMBOL(ttm_base_object_unref);
234
 
228
 
235
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
229
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
236
					       uint32_t key)
230
					       uint32_t key)
237
{
231
{
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;
242
 
236
 
243
//	rcu_read_lock();
237
	rcu_read_lock();
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;
250
	}
244
	}
251
//   rcu_read_unlock();
245
	rcu_read_unlock();
252
 
246
 
253
	return base;
247
	return base;
254
}
248
}
255
EXPORT_SYMBOL(ttm_base_object_lookup);
249
EXPORT_SYMBOL(ttm_base_object_lookup);
256
 
250
 
257
struct ttm_base_object *
251
struct ttm_base_object *
258
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
252
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
259
{
253
{
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;
-
 
258
 
264
 
259
	rcu_read_lock();
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))
270
			base = NULL;
265
			base = NULL;
271
	}
266
	}
-
 
267
	rcu_read_unlock();
272
 
268
 
273
	return base;
269
	return base;
274
}
270
}
275
EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
271
EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
276
 
272
 
277
int ttm_ref_object_add(struct ttm_object_file *tfile,
273
int ttm_ref_object_add(struct ttm_object_file *tfile,
278
		       struct ttm_base_object *base,
274
		       struct ttm_base_object *base,
279
		       enum ttm_ref_type ref_type, bool *existed)
275
		       enum ttm_ref_type ref_type, bool *existed)
280
{
276
{
281
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
277
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
282
	struct ttm_ref_object *ref;
278
	struct ttm_ref_object *ref;
283
	struct drm_hash_item *hash;
279
	struct drm_hash_item *hash;
284
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
280
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
285
	int ret = -EINVAL;
281
	int ret = -EINVAL;
286
 
282
 
287
	if (existed != NULL)
283
	if (existed != NULL)
288
		*existed = true;
284
		*existed = true;
289
 
285
 
290
	while (ret == -EINVAL) {
286
	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
 
293
		if (ret == 0) {
290
		if (ret == 0) {
294
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
291
			ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
295
			if (!kref_get_unless_zero(&ref->kref)) {
292
			if (kref_get_unless_zero(&ref->kref)) {
-
 
293
				rcu_read_unlock();
296
			break;
294
				break;
297
		}
295
			}
298
		}
296
		}
-
 
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),
301
					   false, false);
300
					   false, false);
302
		if (unlikely(ret != 0))
301
		if (unlikely(ret != 0))
303
			return ret;
302
			return ret;
304
		ref = kmalloc(sizeof(*ref), GFP_KERNEL);
303
		ref = kmalloc(sizeof(*ref), GFP_KERNEL);
305
		if (unlikely(ref == NULL)) {
304
		if (unlikely(ref == NULL)) {
306
			ttm_mem_global_free(mem_glob, sizeof(*ref));
305
			ttm_mem_global_free(mem_glob, sizeof(*ref));
307
			return -ENOMEM;
306
			return -ENOMEM;
308
		}
307
		}
309
 
308
 
310
		ref->hash.key = base->hash.key;
309
		ref->hash.key = base->hash.key;
311
		ref->obj = base;
310
		ref->obj = base;
312
		ref->tfile = tfile;
311
		ref->tfile = tfile;
313
		ref->ref_type = ref_type;
312
		ref->ref_type = ref_type;
314
		kref_init(&ref->kref);
313
		kref_init(&ref->kref);
315
 
314
 
316
		spin_lock(&tfile->lock);
315
		spin_lock(&tfile->lock);
317
		ret = drm_ht_insert_item_rcu(ht, &ref->hash);
316
		ret = drm_ht_insert_item_rcu(ht, &ref->hash);
318
 
317
 
319
		if (likely(ret == 0)) {
318
		if (likely(ret == 0)) {
320
			list_add_tail(&ref->head, &tfile->ref_list);
319
			list_add_tail(&ref->head, &tfile->ref_list);
321
			kref_get(&base->refcount);
320
			kref_get(&base->refcount);
322
			spin_unlock(&tfile->lock);
321
			spin_unlock(&tfile->lock);
323
			if (existed != NULL)
322
			if (existed != NULL)
324
				*existed = false;
323
				*existed = false;
325
			break;
324
			break;
326
		}
325
		}
327
 
326
 
328
		spin_unlock(&tfile->lock);
327
		spin_unlock(&tfile->lock);
329
		BUG_ON(ret != -EINVAL);
328
		BUG_ON(ret != -EINVAL);
330
 
329
 
331
		ttm_mem_global_free(mem_glob, sizeof(*ref));
330
		ttm_mem_global_free(mem_glob, sizeof(*ref));
332
		kfree(ref);
331
		kfree(ref);
333
	}
332
	}
334
 
333
 
335
	return ret;
334
	return ret;
336
}
335
}
337
EXPORT_SYMBOL(ttm_ref_object_add);
336
EXPORT_SYMBOL(ttm_ref_object_add);
338
 
337
 
339
static void ttm_ref_object_release(struct kref *kref)
338
static void ttm_ref_object_release(struct kref *kref)
340
{
339
{
341
	struct ttm_ref_object *ref =
340
	struct ttm_ref_object *ref =
342
	    container_of(kref, struct ttm_ref_object, kref);
341
	    container_of(kref, struct ttm_ref_object, kref);
343
	struct ttm_base_object *base = ref->obj;
342
	struct ttm_base_object *base = ref->obj;
344
	struct ttm_object_file *tfile = ref->tfile;
343
	struct ttm_object_file *tfile = ref->tfile;
345
	struct drm_open_hash *ht;
344
	struct drm_open_hash *ht;
346
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
345
	struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob;
347
 
346
 
348
	ht = &tfile->ref_hash[ref->ref_type];
347
	ht = &tfile->ref_hash[ref->ref_type];
349
	(void)drm_ht_remove_item_rcu(ht, &ref->hash);
348
	(void)drm_ht_remove_item_rcu(ht, &ref->hash);
350
	list_del(&ref->head);
349
	list_del(&ref->head);
351
	spin_unlock(&tfile->lock);
350
	spin_unlock(&tfile->lock);
352
 
351
 
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);
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);
360
}
359
}
361
 
360
 
362
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
361
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
363
			      unsigned long key, enum ttm_ref_type ref_type)
362
			      unsigned long key, enum ttm_ref_type ref_type)
364
{
363
{
365
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
364
	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
366
	struct ttm_ref_object *ref;
365
	struct ttm_ref_object *ref;
367
	struct drm_hash_item *hash;
366
	struct drm_hash_item *hash;
368
	int ret;
367
	int ret;
369
 
368
 
370
	spin_lock(&tfile->lock);
369
	spin_lock(&tfile->lock);
371
	ret = drm_ht_find_item(ht, key, &hash);
370
	ret = drm_ht_find_item(ht, key, &hash);
372
	if (unlikely(ret != 0)) {
371
	if (unlikely(ret != 0)) {
373
		spin_unlock(&tfile->lock);
372
		spin_unlock(&tfile->lock);
374
		return -EINVAL;
373
		return -EINVAL;
375
	}
374
	}
376
	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
375
	ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
377
	kref_put(&ref->kref, ttm_ref_object_release);
376
	kref_put(&ref->kref, ttm_ref_object_release);
378
	spin_unlock(&tfile->lock);
377
	spin_unlock(&tfile->lock);
379
	return 0;
378
	return 0;
380
}
379
}
381
EXPORT_SYMBOL(ttm_ref_object_base_unref);
380
EXPORT_SYMBOL(ttm_ref_object_base_unref);
382
 
381
 
383
void ttm_object_file_release(struct ttm_object_file **p_tfile)
382
void ttm_object_file_release(struct ttm_object_file **p_tfile)
384
{
383
{
385
	struct ttm_ref_object *ref;
384
	struct ttm_ref_object *ref;
386
	struct list_head *list;
385
	struct list_head *list;
387
	unsigned int i;
386
	unsigned int i;
388
	struct ttm_object_file *tfile = *p_tfile;
387
	struct ttm_object_file *tfile = *p_tfile;
389
 
388
 
390
	*p_tfile = NULL;
389
	*p_tfile = NULL;
391
	spin_lock(&tfile->lock);
390
	spin_lock(&tfile->lock);
392
 
391
 
393
	/*
392
	/*
394
	 * Since we release the lock within the loop, we have to
393
	 * Since we release the lock within the loop, we have to
395
	 * restart it from the beginning each time.
394
	 * restart it from the beginning each time.
396
	 */
395
	 */
397
 
396
 
398
	while (!list_empty(&tfile->ref_list)) {
397
	while (!list_empty(&tfile->ref_list)) {
399
		list = tfile->ref_list.next;
398
		list = tfile->ref_list.next;
400
		ref = list_entry(list, struct ttm_ref_object, head);
399
		ref = list_entry(list, struct ttm_ref_object, head);
401
		ttm_ref_object_release(&ref->kref);
400
		ttm_ref_object_release(&ref->kref);
402
	}
401
	}
403
 
402
 
404
	for (i = 0; i < TTM_REF_NUM; ++i)
403
	for (i = 0; i < TTM_REF_NUM; ++i)
405
		drm_ht_remove(&tfile->ref_hash[i]);
404
		drm_ht_remove(&tfile->ref_hash[i]);
406
 
405
 
407
	spin_unlock(&tfile->lock);
406
	spin_unlock(&tfile->lock);
408
	ttm_object_file_unref(&tfile);
407
	ttm_object_file_unref(&tfile);
409
}
408
}
410
EXPORT_SYMBOL(ttm_object_file_release);
409
EXPORT_SYMBOL(ttm_object_file_release);
411
 
410
 
412
struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
411
struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
413
					     unsigned int hash_order)
412
					     unsigned int hash_order)
414
{
413
{
415
	struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
414
	struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
416
	unsigned int i;
415
	unsigned int i;
417
	unsigned int j = 0;
416
	unsigned int j = 0;
418
	int ret;
417
	int ret;
419
 
418
 
420
	if (unlikely(tfile == NULL))
419
	if (unlikely(tfile == NULL))
421
		return NULL;
420
		return NULL;
422
 
421
 
423
	spin_lock_init(&tfile->lock);
422
	spin_lock_init(&tfile->lock);
424
	tfile->tdev = tdev;
423
	tfile->tdev = tdev;
425
	kref_init(&tfile->refcount);
424
	kref_init(&tfile->refcount);
426
	INIT_LIST_HEAD(&tfile->ref_list);
425
	INIT_LIST_HEAD(&tfile->ref_list);
427
 
426
 
428
	for (i = 0; i < TTM_REF_NUM; ++i) {
427
	for (i = 0; i < TTM_REF_NUM; ++i) {
429
		ret = drm_ht_create(&tfile->ref_hash[i], hash_order);
428
		ret = drm_ht_create(&tfile->ref_hash[i], hash_order);
430
		if (ret) {
429
		if (ret) {
431
			j = i;
430
			j = i;
432
			goto out_err;
431
			goto out_err;
433
		}
432
		}
434
	}
433
	}
435
 
434
 
436
	return tfile;
435
	return tfile;
437
out_err:
436
out_err:
438
	for (i = 0; i < j; ++i)
437
	for (i = 0; i < j; ++i)
439
		drm_ht_remove(&tfile->ref_hash[i]);
438
		drm_ht_remove(&tfile->ref_hash[i]);
440
 
439
 
441
	kfree(tfile);
440
	kfree(tfile);
442
 
441
 
443
	return NULL;
442
	return NULL;
444
}
443
}
445
EXPORT_SYMBOL(ttm_object_file_init);
444
EXPORT_SYMBOL(ttm_object_file_init);
446
 
445
 
447
struct ttm_object_device *
446
struct ttm_object_device *
448
ttm_object_device_init(struct ttm_mem_global *mem_glob,
447
ttm_object_device_init(struct ttm_mem_global *mem_glob,
449
		       unsigned int hash_order,
448
		       unsigned int hash_order,
450
		       const struct dma_buf_ops *ops)
449
		       const struct dma_buf_ops *ops)
451
{
450
{
452
	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
451
	struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
453
	int ret;
452
	int ret;
454
 
453
 
455
	if (unlikely(tdev == NULL))
454
	if (unlikely(tdev == NULL))
456
		return NULL;
455
		return NULL;
457
 
456
 
458
	tdev->mem_glob = mem_glob;
457
	tdev->mem_glob = mem_glob;
459
	spin_lock_init(&tdev->object_lock);
458
	spin_lock_init(&tdev->object_lock);
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;
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));
470
		return tdev;
469
	return tdev;
471
 
470
 
472
out_no_object_hash:
471
out_no_object_hash:
473
	kfree(tdev);
472
	kfree(tdev);
474
	return NULL;
473
	return NULL;
475
}
474
}
476
EXPORT_SYMBOL(ttm_object_device_init);
475
EXPORT_SYMBOL(ttm_object_device_init);
477
 
476
 
478
void ttm_object_device_release(struct ttm_object_device **p_tdev)
477
void ttm_object_device_release(struct ttm_object_device **p_tdev)
479
{
478
{
480
	struct ttm_object_device *tdev = *p_tdev;
479
	struct ttm_object_device *tdev = *p_tdev;
481
 
480
 
482
	*p_tdev = NULL;
481
	*p_tdev = NULL;
483
 
482
 
484
	spin_lock(&tdev->object_lock);
483
	spin_lock(&tdev->object_lock);
485
	drm_ht_remove(&tdev->object_hash);
484
	drm_ht_remove(&tdev->object_hash);
486
	spin_unlock(&tdev->object_lock);
485
	spin_unlock(&tdev->object_lock);
487
 
486
 
488
	kfree(tdev);
487
	kfree(tdev);
489
}
488
}
490
EXPORT_SYMBOL(ttm_object_device_release);
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
}
-
 
716
EXPORT_SYMBOL(ttm_prime_object_init);