@@ -413,6 +413,8 @@ static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
* @bo: A pointer to a struct ttm_buffer_object.
* @new_obj: A pointer to a pointer to a newly created ttm_buffer_object,
* holding the data of @bo with the old placement.
+ * @sync_obj: the sync object caller is responsible to take a reference on
+ * behalf of this function
*
* This is a utility function that may be called after an accelerated move
* has been scheduled. A new buffer object is created as a placeholder for
@@ -423,7 +425,8 @@ static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
*/
static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
- struct ttm_buffer_object **new_obj)
+ struct ttm_buffer_object **new_obj,
+ void sync_obj)
{
struct ttm_buffer_object *fbo;
struct ttm_bo_device *bdev = bo->bdev;
@@ -448,7 +451,8 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
fbo->vm_node = NULL;
atomic_set(&fbo->cpu_writers, 0);
- fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
+ /* reference on sync obj is taken by the caller of this function */
+ fbo->sync_obj = sync_obj;
kref_init(&fbo->list_kref);
kref_init(&fbo->kref);
fbo->destroy = &ttm_transfered_destroy;
@@ -652,6 +656,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
}
ttm_bo_free_old_node(bo);
} else {
+ void *sync_obj;
+
/**
* This should help pipeline ordinary buffer moves.
*
@@ -662,12 +668,14 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
- /* ttm_buffer_object_transfer accesses bo->sync_obj */
- ret = ttm_buffer_object_transfer(bo, &ghost_obj);
+ /* take the ref on the sync object before releasing the spinlock */
+ sync_obj = driver->sync_obj_ref(bo->sync_obj);
spin_unlock(&bdev->fence_lock);
+
if (tmp_obj)
driver->sync_obj_unref(&tmp_obj);
+ ret = ttm_buffer_object_transfer(bo, &ghost_obj, sync_obj);
if (ret)
return ret;