diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2012-11-06 06:31:50 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-11-20 01:15:05 -0500 |
commit | cdad05216c2b2edfe92a9f87d6ae51aab277f3b2 (patch) | |
tree | 1ba899709b77745acec655d0a8eea3f08c97a885 /drivers/gpu/drm/ttm/ttm_object.c | |
parent | 4b20db3de8dab005b07c74161cb041db8c5ff3a7 (diff) |
drm/ttm, drm/vmwgfx: Use RCU locking for object lookups v3
The mostly used lookup+get put+potential_destroy path of TTM objects
is converted to use RCU locks. This will substantially decrease the amount
of locked bus cycles during normal operation.
Since we use kfree_rcu to free the objects, no rcu synchronization is needed
at module unload time.
v2: Don't touch include/linux/kref.h
v3: Adapt to kref_get_unless_zero return value change
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_object.c')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_object.c | 30 |
1 files changed, 11 insertions, 19 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c index c7857874956a..f18eeb458139 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); | 160 | spin_lock(&tdev->object_lock); |
161 | kref_init(&base->refcount); | 161 | kref_init(&base->refcount); |
162 | ret = drm_ht_just_insert_please(&tdev->object_hash, | 162 | ret = drm_ht_just_insert_please(&tdev->object_hash, |
163 | &base->hash, | 163 | &base->hash, |
164 | (unsigned long)base, 31, 0, 0); | 164 | (unsigned long)base, 31, 0, 0); |
165 | write_unlock(&tdev->object_lock); | 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 | ||
@@ -186,30 +186,22 @@ static void ttm_release_base(struct kref *kref) | |||
186 | container_of(kref, struct ttm_base_object, refcount); | 186 | container_of(kref, struct ttm_base_object, refcount); |
187 | struct ttm_object_device *tdev = base->tfile->tdev; | 187 | struct ttm_object_device *tdev = base->tfile->tdev; |
188 | 188 | ||
189 | spin_lock(&tdev->object_lock); | ||
189 | (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); | 190 | (void)drm_ht_remove_item(&tdev->object_hash, &base->hash); |
190 | write_unlock(&tdev->object_lock); | 191 | spin_unlock(&tdev->object_lock); |
191 | if (base->refcount_release) { | 192 | if (base->refcount_release) { |
192 | ttm_object_file_unref(&base->tfile); | 193 | ttm_object_file_unref(&base->tfile); |
193 | base->refcount_release(&base); | 194 | base->refcount_release(&base); |
194 | } | 195 | } |
195 | write_lock(&tdev->object_lock); | ||
196 | } | 196 | } |
197 | 197 | ||
198 | void ttm_base_object_unref(struct ttm_base_object **p_base) | 198 | void ttm_base_object_unref(struct ttm_base_object **p_base) |
199 | { | 199 | { |
200 | struct ttm_base_object *base = *p_base; | 200 | struct ttm_base_object *base = *p_base; |
201 | struct ttm_object_device *tdev = base->tfile->tdev; | ||
202 | 201 | ||
203 | *p_base = NULL; | 202 | *p_base = NULL; |
204 | 203 | ||
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); | 204 | kref_put(&base->refcount, ttm_release_base); |
212 | write_unlock(&tdev->object_lock); | ||
213 | } | 205 | } |
214 | EXPORT_SYMBOL(ttm_base_object_unref); | 206 | EXPORT_SYMBOL(ttm_base_object_unref); |
215 | 207 | ||
@@ -221,14 +213,14 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, | |||
221 | struct drm_hash_item *hash; | 213 | struct drm_hash_item *hash; |
222 | int ret; | 214 | int ret; |
223 | 215 | ||
224 | read_lock(&tdev->object_lock); | 216 | rcu_read_lock(); |
225 | ret = drm_ht_find_item(&tdev->object_hash, key, &hash); | 217 | ret = drm_ht_find_item(&tdev->object_hash, key, &hash); |
226 | 218 | ||
227 | if (likely(ret == 0)) { | 219 | if (likely(ret == 0)) { |
228 | base = drm_hash_entry(hash, struct ttm_base_object, hash); | 220 | base = drm_hash_entry(hash, struct ttm_base_object, hash); |
229 | kref_get(&base->refcount); | 221 | ret = kref_get_unless_zero(&base->refcount) ? 0 : -EINVAL; |
230 | } | 222 | } |
231 | read_unlock(&tdev->object_lock); | 223 | rcu_read_unlock(); |
232 | 224 | ||
233 | if (unlikely(ret != 0)) | 225 | if (unlikely(ret != 0)) |
234 | return NULL; | 226 | return NULL; |
@@ -426,7 +418,7 @@ struct ttm_object_device *ttm_object_device_init(struct ttm_mem_global | |||
426 | return NULL; | 418 | return NULL; |
427 | 419 | ||
428 | tdev->mem_glob = mem_glob; | 420 | tdev->mem_glob = mem_glob; |
429 | rwlock_init(&tdev->object_lock); | 421 | spin_lock_init(&tdev->object_lock); |
430 | atomic_set(&tdev->object_count, 0); | 422 | atomic_set(&tdev->object_count, 0); |
431 | ret = drm_ht_create(&tdev->object_hash, hash_order); | 423 | ret = drm_ht_create(&tdev->object_hash, hash_order); |
432 | 424 | ||
@@ -444,9 +436,9 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev) | |||
444 | 436 | ||
445 | *p_tdev = NULL; | 437 | *p_tdev = NULL; |
446 | 438 | ||
447 | write_lock(&tdev->object_lock); | 439 | spin_lock(&tdev->object_lock); |
448 | drm_ht_remove(&tdev->object_hash); | 440 | drm_ht_remove(&tdev->object_hash); |
449 | write_unlock(&tdev->object_lock); | 441 | spin_unlock(&tdev->object_lock); |
450 | 442 | ||
451 | kfree(tdev); | 443 | kfree(tdev); |
452 | } | 444 | } |