diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_object.c')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_object.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c index c7857874956a..58a5f3261c0b 100644 --- a/drivers/gpu/drm/ttm/ttm_object.c +++ b/drivers/gpu/drm/ttm/ttm_object.c | |||
@@ -80,7 +80,7 @@ struct ttm_object_file { | |||
80 | */ | 80 | */ |
81 | 81 | ||
82 | struct ttm_object_device { | 82 | struct ttm_object_device { |
83 | rwlock_t object_lock; | 83 | spinlock_t object_lock; |
84 | struct drm_open_hash object_hash; | 84 | struct drm_open_hash object_hash; |
85 | atomic_t object_count; | 85 | atomic_t object_count; |
86 | struct ttm_mem_global *mem_glob; | 86 | struct ttm_mem_global *mem_glob; |
@@ -157,12 +157,12 @@ int ttm_base_object_init(struct ttm_object_file *tfile, | |||
157 | base->refcount_release = refcount_release; | 157 | base->refcount_release = refcount_release; |
158 | base->ref_obj_release = ref_obj_release; | 158 | base->ref_obj_release = ref_obj_release; |
159 | base->object_type = object_type; | 159 | base->object_type = object_type; |
160 | write_lock(&tdev->object_lock); | ||
161 | kref_init(&base->refcount); | 160 | kref_init(&base->refcount); |
162 | ret = drm_ht_just_insert_please(&tdev->object_hash, | 161 | spin_lock(&tdev->object_lock); |
163 | &base->hash, | 162 | ret = drm_ht_just_insert_please_rcu(&tdev->object_hash, |
164 | (unsigned long)base, 31, 0, 0); | 163 | &base->hash, |
165 | write_unlock(&tdev->object_lock); | 164 | (unsigned long)base, 31, 0, 0); |
165 | spin_unlock(&tdev->object_lock); | ||
166 | if (unlikely(ret != 0)) | 166 | if (unlikely(ret != 0)) |
167 | goto out_err0; | 167 | goto out_err0; |
168 | 168 | ||
@@ -174,7 +174,9 @@ int ttm_base_object_init(struct ttm_object_file *tfile, | |||
174 | 174 | ||
175 | return 0; | 175 | return 0; |
176 | out_err1: | 176 | out_err1: |
177 | (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); | 177 | spin_lock(&tdev->object_lock); |
178 | (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash); | ||
179 | spin_unlock(&tdev->object_lock); | ||
178 | out_err0: | 180 | out_err0: |
179 | return ret; | 181 | return ret; |
180 | } | 182 | } |
@@ -186,30 +188,29 @@ static void ttm_release_base(struct kref *kref) | |||
186 | container_of(kref, struct ttm_base_object, refcount); | 188 | container_of(kref, struct ttm_base_object, refcount); |
187 | struct ttm_object_device *tdev = base->tfile->tdev; | 189 | struct ttm_object_device *tdev = base->tfile->tdev; |
188 | 190 | ||
189 | (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); | 191 | spin_lock(&tdev->object_lock); |
190 | write_unlock(&tdev->object_lock); | 192 | (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash); |
193 | spin_unlock(&tdev->object_lock); | ||
194 | |||
195 | /* | ||
196 | * Note: We don't use synchronize_rcu() here because it's far | ||
197 | * too slow. It's up to the user to free the object using | ||
198 | * call_rcu() or ttm_base_object_kfree(). | ||
199 | */ | ||
200 | |||
191 | if (base->refcount_release) { | 201 | if (base->refcount_release) { |
192 | ttm_object_file_unref(&base->tfile); | 202 | ttm_object_file_unref(&base->tfile); |
193 | base->refcount_release(&base); | 203 | base->refcount_release(&base); |
194 | } | 204 | } |
195 | write_lock(&tdev->object_lock); | ||
196 | } | 205 | } |
197 | 206 | ||
198 | void ttm_base_object_unref(struct ttm_base_object **p_base) | 207 | void ttm_base_object_unref(struct ttm_base_object **p_base) |
199 | { | 208 | { |
200 | struct ttm_base_object *base = *p_base; | 209 | struct ttm_base_object *base = *p_base; |
201 | struct ttm_object_device *tdev = base->tfile->tdev; | ||
202 | 210 | ||
203 | *p_base = NULL; | 211 | *p_base = NULL; |
204 | 212 | ||
205 | /* | ||
206 | * Need to take the lock here to avoid racing with | ||
207 | * users trying to look up the object. | ||
208 | */ | ||
209 | |||
210 | write_lock(&tdev->object_lock); | ||
211 | kref_put(&base->refcount, ttm_release_base); | 213 | kref_put(&base->refcount, ttm_release_base); |
212 | write_unlock(&tdev->object_lock); | ||
213 | } | 214 | } |
214 | EXPORT_SYMBOL(ttm_base_object_unref); | 215 | EXPORT_SYMBOL(ttm_base_object_unref); |
215 | 216 | ||
@@ -221,14 +222,14 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, | |||
221 | struct drm_hash_item *hash; | 222 | struct drm_hash_item *hash; |
222 | int ret; | 223 | int ret; |
223 | 224 | ||
224 | read_lock(&tdev->object_lock); | 225 | rcu_read_lock(); |
225 | ret = drm_ht_find_item(&tdev->object_hash, key, &hash); | 226 | ret = drm_ht_find_item_rcu(&tdev->object_hash, key, &hash); |
226 | 227 | ||
227 | if (likely(ret == 0)) { | 228 | if (likely(ret == 0)) { |
228 | base = drm_hash_entry(hash, struct ttm_base_object, hash); | 229 | base = drm_hash_entry(hash, struct ttm_base_object, hash); |
229 | kref_get(&base->refcount); | 230 | ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL; |
230 | } | 231 | } |
231 | read_unlock(&tdev->object_lock); | 232 | rcu_read_unlock(); |
232 | 233 | ||
233 | if (unlikely(ret != 0)) | 234 | if (unlikely(ret != 0)) |
234 | return NULL; | 235 | return NULL; |
@@ -426,7 +427,7 @@ struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global | |||
426 | return NULL; | 427 | return NULL; |
427 | 428 | ||
428 | tdev->mem_glob = mem_glob; | 429 | tdev->mem_glob = mem_glob; |
429 | rwlock_init(&tdev->object_lock); | 430 | spin_lock_init(&tdev->object_lock); |
430 | atomic_set(&tdev->object_count, 0); | 431 | atomic_set(&tdev->object_count, 0); |
431 | ret = drm_ht_create(&tdev->object_hash, hash_order); | 432 | ret = drm_ht_create(&tdev->object_hash, hash_order); |
432 | 433 | ||
@@ -444,9 +445,9 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev) | |||
444 | 445 | ||
445 | *p_tdev = NULL; | 446 | *p_tdev = NULL; |
446 | 447 | ||
447 | write_lock(&tdev->object_lock); | 448 | spin_lock(&tdev->object_lock); |
448 | drm_ht_remove(&tdev->object_hash); | 449 | drm_ht_remove(&tdev->object_hash); |
449 | write_unlock(&tdev->object_lock); | 450 | spin_unlock(&tdev->object_lock); |
450 | 451 | ||
451 | kfree(tdev); | 452 | kfree(tdev); |
452 | } | 453 | } |