Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/ttm: Improved fencing of buffer object lists

Drastically reduce the number of spin lock / unlock operations by performing
unreserving and fencing under global locks.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Jerome Glisse <j.glisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>

authored by

Thomas Hellstrom and committed by
Dave Airlie
95762c2b 702adba2

+45 -14
+8 -3
drivers/gpu/drm/ttm/ttm_bo.c
··· 299 299 return ret; 300 300 } 301 301 302 + void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo) 303 + { 304 + ttm_bo_add_to_lru(bo); 305 + atomic_set(&bo->reserved, 0); 306 + wake_up_all(&bo->event_queue); 307 + } 308 + 302 309 void ttm_bo_unreserve(struct ttm_buffer_object *bo) 303 310 { 304 311 struct ttm_bo_global *glob = bo->glob; 305 312 306 313 spin_lock(&glob->lru_lock); 307 - ttm_bo_add_to_lru(bo); 308 - atomic_set(&bo->reserved, 0); 309 - wake_up_all(&bo->event_queue); 314 + ttm_bo_unreserve_locked(bo); 310 315 spin_unlock(&glob->lru_lock); 311 316 } 312 317 EXPORT_SYMBOL(ttm_bo_unreserve);
+25 -11
drivers/gpu/drm/ttm/ttm_execbuf_util.c
··· 200 200 void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj) 201 201 { 202 202 struct ttm_validate_buffer *entry; 203 + struct ttm_buffer_object *bo; 204 + struct ttm_bo_global *glob; 205 + struct ttm_bo_device *bdev; 206 + struct ttm_bo_driver *driver; 207 + 208 + if (list_empty(list)) 209 + return; 210 + 211 + bo = list_first_entry(list, struct ttm_validate_buffer, head)->bo; 212 + bdev = bo->bdev; 213 + driver = bdev->driver; 214 + glob = bo->glob; 215 + 216 + spin_lock(&bdev->fence_lock); 217 + spin_lock(&glob->lru_lock); 203 218 204 219 list_for_each_entry(entry, list, head) { 205 - struct ttm_buffer_object *bo = entry->bo; 206 - struct ttm_bo_device *bdev = bo->bdev; 207 - struct ttm_bo_driver *driver = bdev->driver; 208 - void *old_sync_obj; 209 - 210 - spin_lock(&bdev->fence_lock); 211 - old_sync_obj = bo->sync_obj; 220 + bo = entry->bo; 221 + entry->old_sync_obj = bo->sync_obj; 212 222 bo->sync_obj = driver->sync_obj_ref(sync_obj); 213 223 bo->sync_obj_arg = entry->new_sync_obj_arg; 214 - spin_unlock(&bdev->fence_lock); 215 - ttm_bo_unreserve(bo); 224 + ttm_bo_unreserve_locked(bo); 216 225 entry->reserved = false; 217 - if (old_sync_obj) 218 - driver->sync_obj_unref(&old_sync_obj); 226 + } 227 + spin_unlock(&glob->lru_lock); 228 + spin_unlock(&bdev->fence_lock); 229 + 230 + list_for_each_entry(entry, list, head) { 231 + if (entry->old_sync_obj) 232 + driver->sync_obj_unref(&entry->old_sync_obj); 219 233 } 220 234 } 221 235 EXPORT_SYMBOL(ttm_eu_fence_buffer_objects);
+10
include/drm/ttm/ttm_bo_driver.h
··· 910 910 extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); 911 911 912 912 /** 913 + * ttm_bo_unreserve_locked 914 + * 915 + * @bo: A pointer to a struct ttm_buffer_object. 916 + * 917 + * Unreserve a previous reservation of @bo. 918 + * Needs to be called with struct ttm_bo_global::lru_lock held. 919 + */ 920 + extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo); 921 + 922 + /** 913 923 * ttm_bo_wait_unreserved 914 924 * 915 925 * @bo: A pointer to a struct ttm_buffer_object.
+2
include/drm/ttm/ttm_execbuf_util.h
··· 44 44 * @reserved: Indicates whether @bo has been reserved for validation. 45 45 * @removed: Indicates whether @bo has been removed from lru lists. 46 46 * @put_count: Number of outstanding references on bo::list_kref. 47 + * @old_sync_obj: Pointer to a sync object about to be unreferenced 47 48 */ 48 49 49 50 struct ttm_validate_buffer { ··· 54 53 bool reserved; 55 54 bool removed; 56 55 int put_count; 56 + void *old_sync_obj; 57 57 }; 58 58 59 59 /**