|
@@ -524,52 +524,44 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all)
|
|
|
static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
|
|
|
{
|
|
|
struct ttm_bo_global *glob = bdev->glob;
|
|
|
- struct ttm_buffer_object *entry, *nentry;
|
|
|
- struct list_head *list, *next;
|
|
|
- int ret;
|
|
|
+ struct ttm_buffer_object *entry = NULL;
|
|
|
+ int ret = 0;
|
|
|
|
|
|
spin_lock(&glob->lru_lock);
|
|
|
- list_for_each_safe(list, next, &bdev->ddestroy) {
|
|
|
- entry = list_entry(list, struct ttm_buffer_object, ddestroy);
|
|
|
- nentry = NULL;
|
|
|
+ if (list_empty(&bdev->ddestroy))
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
- /*
|
|
|
- * Protect the next list entry from destruction while we
|
|
|
- * unlock the lru_lock.
|
|
|
- */
|
|
|
+ entry = list_first_entry(&bdev->ddestroy,
|
|
|
+ struct ttm_buffer_object, ddestroy);
|
|
|
+ kref_get(&entry->list_kref);
|
|
|
+
|
|
|
+ for (;;) {
|
|
|
+ struct ttm_buffer_object *nentry = NULL;
|
|
|
|
|
|
- if (next != &bdev->ddestroy) {
|
|
|
- nentry = list_entry(next, struct ttm_buffer_object,
|
|
|
- ddestroy);
|
|
|
+ if (entry->ddestroy.next != &bdev->ddestroy) {
|
|
|
+ nentry = list_first_entry(&entry->ddestroy,
|
|
|
+ struct ttm_buffer_object, ddestroy);
|
|
|
kref_get(&nentry->list_kref);
|
|
|
}
|
|
|
- kref_get(&entry->list_kref);
|
|
|
|
|
|
spin_unlock(&glob->lru_lock);
|
|
|
ret = ttm_bo_cleanup_refs(entry, remove_all);
|
|
|
kref_put(&entry->list_kref, ttm_bo_release_list);
|
|
|
+ entry = nentry;
|
|
|
+
|
|
|
+ if (ret || !entry)
|
|
|
+ goto out;
|
|
|
|
|
|
spin_lock(&glob->lru_lock);
|
|
|
- if (nentry) {
|
|
|
- bool next_onlist = !list_empty(next);
|
|
|
- spin_unlock(&glob->lru_lock);
|
|
|
- kref_put(&nentry->list_kref, ttm_bo_release_list);
|
|
|
- spin_lock(&glob->lru_lock);
|
|
|
- /*
|
|
|
- * Someone might have raced us and removed the
|
|
|
- * next entry from the list. We don't bother restarting
|
|
|
- * list traversal.
|
|
|
- */
|
|
|
-
|
|
|
- if (!next_onlist)
|
|
|
- break;
|
|
|
- }
|
|
|
- if (ret)
|
|
|
+ if (list_empty(&entry->ddestroy))
|
|
|
break;
|
|
|
}
|
|
|
- ret = !list_empty(&bdev->ddestroy);
|
|
|
- spin_unlock(&glob->lru_lock);
|
|
|
|
|
|
+out_unlock:
|
|
|
+ spin_unlock(&glob->lru_lock);
|
|
|
+out:
|
|
|
+ if (entry)
|
|
|
+ kref_put(&entry->list_kref, ttm_bo_release_list);
|
|
|
return ret;
|
|
|
}
|
|
|
|