diff options
| author | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2013-01-15 08:57:05 -0500 |
|---|---|---|
| committer | Maarten Lankhorst <maarten.lankhorst@canonical.com> | 2013-01-15 08:57:05 -0500 |
| commit | 5e45d7dfd74100d622f9cdc70bfd1f9fae1671de (patch) | |
| tree | b12de2542f55d332a73fcd7d863bd2e45fd7d4ef | |
| parent | 7a1863084c9d90ce4b67d645bf9b0f1612e68f62 (diff) | |
drm/ttm: add ttm_bo_reserve_slowpath
Instead of dropping everything, waiting for the bo to be unreserved
and trying over, a better strategy would be to do a blocking wait.
This can be mapped a lot better to a mutex_lock-like call.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 47 | ||||
| -rw-r--r-- | include/drm/ttm/ttm_bo_driver.h | 30 |
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e8e4814b1295..4dd6f9e77a7d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -310,6 +310,53 @@ int ttm_bo_reserve(struct ttm_buffer_object *bo, | |||
| 310 | return ret; | 310 | return ret; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo, | ||
| 314 | bool interruptible, uint32_t sequence) | ||
| 315 | { | ||
| 316 | bool wake_up = false; | ||
| 317 | int ret; | ||
| 318 | |||
| 319 | while (unlikely(atomic_xchg(&bo->reserved, 1) != 0)) { | ||
| 320 | WARN_ON(bo->seq_valid && sequence == bo->val_seq); | ||
| 321 | |||
| 322 | ret = ttm_bo_wait_unreserved(bo, interruptible); | ||
| 323 | |||
| 324 | if (unlikely(ret)) | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | if ((bo->val_seq - sequence < (1 << 31)) || !bo->seq_valid) | ||
| 329 | wake_up = true; | ||
| 330 | |||
| 331 | /** | ||
| 332 | * Wake up waiters that may need to recheck for deadlock, | ||
| 333 | * if we decreased the sequence number. | ||
| 334 | */ | ||
| 335 | bo->val_seq = sequence; | ||
| 336 | bo->seq_valid = true; | ||
| 337 | if (wake_up) | ||
| 338 | wake_up_all(&bo->event_queue); | ||
| 339 | |||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 343 | int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, | ||
| 344 | bool interruptible, uint32_t sequence) | ||
| 345 | { | ||
| 346 | struct ttm_bo_global *glob = bo->glob; | ||
| 347 | int put_count, ret; | ||
| 348 | |||
| 349 | ret = ttm_bo_reserve_slowpath_nolru(bo, interruptible, sequence); | ||
| 350 | if (likely(!ret)) { | ||
| 351 | spin_lock(&glob->lru_lock); | ||
| 352 | put_count = ttm_bo_del_from_lru(bo); | ||
| 353 | spin_unlock(&glob->lru_lock); | ||
| 354 | ttm_bo_list_ref_sub(bo, put_count, true); | ||
| 355 | } | ||
| 356 | return ret; | ||
| 357 | } | ||
| 358 | EXPORT_SYMBOL(ttm_bo_reserve_slowpath); | ||
| 359 | |||
| 313 | void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo) | 360 | void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo) |
| 314 | { | 361 | { |
| 315 | ttm_bo_add_to_lru(bo); | 362 | ttm_bo_add_to_lru(bo); |
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 6fff43222e20..5af71af6bf88 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
| @@ -821,6 +821,36 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, | |||
| 821 | bool interruptible, | 821 | bool interruptible, |
| 822 | bool no_wait, bool use_sequence, uint32_t sequence); | 822 | bool no_wait, bool use_sequence, uint32_t sequence); |
| 823 | 823 | ||
| 824 | /** | ||
| 825 | * ttm_bo_reserve_slowpath_nolru: | ||
| 826 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 827 | * @interruptible: Sleep interruptible if waiting. | ||
| 828 | * @sequence: Set (@bo)->sequence to this value after lock | ||
| 829 | * | ||
| 830 | * This is called after ttm_bo_reserve returns -EAGAIN and we backed off | ||
| 831 | * from all our other reservations. Because there are no other reservations | ||
| 832 | * held by us, this function cannot deadlock any more. | ||
| 833 | * | ||
| 834 | * Will not remove reserved buffers from the lru lists. | ||
| 835 | * Otherwise identical to ttm_bo_reserve_slowpath. | ||
| 836 | */ | ||
| 837 | extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo, | ||
| 838 | bool interruptible, | ||
| 839 | uint32_t sequence); | ||
| 840 | |||
| 841 | |||
| 842 | /** | ||
| 843 | * ttm_bo_reserve_slowpath: | ||
| 844 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 845 | * @interruptible: Sleep interruptible if waiting. | ||
| 846 | * @sequence: Set (@bo)->sequence to this value after lock | ||
| 847 | * | ||
| 848 | * This is called after ttm_bo_reserve returns -EAGAIN and we backed off | ||
| 849 | * from all our other reservations. Because there are no other reservations | ||
| 850 | * held by us, this function cannot deadlock any more. | ||
| 851 | */ | ||
| 852 | extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, | ||
| 853 | bool interruptible, uint32_t sequence); | ||
| 824 | 854 | ||
| 825 | /** | 855 | /** |
| 826 | * ttm_bo_reserve_nolru: | 856 | * ttm_bo_reserve_nolru: |
