[PATCH] drm/ttm: Use RCU for ttm_mem_type_manager.move fence
Chris Wilson
chris at chris-wilson.co.uk
Mon Aug 29 16:57:11 UTC 2016
The ttm_mem_type_manager.move tracks the fence for the last migration on
the memory manager. Currently it is accessed under its own spinlock to
ensure that the fence doesn't disappear from underneath it. We can
translate the reader to acquire a reference to the fence using
fence_get_rcu_safe() which ensures that the fence cannot be reallocated
as the reference is acquired.
Suggested-by: Christian König <christian.koenig at amd.com>
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Christian König <christian.koenig at amd.com>
---
drivers/gpu/drm/ttm/ttm_bo.c | 24 ++++++++++++++++--------
drivers/gpu/drm/ttm/ttm_bo_util.c | 12 ++++++++----
include/drm/ttm/ttm_bo_driver.h | 2 +-
3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 42c074a9c955..422d9b39d8ae 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -797,9 +797,9 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
struct fence *fence;
int ret;
- spin_lock(&man->move_lock);
- fence = fence_get(man->move);
- spin_unlock(&man->move_lock);
+ rcu_read_lock();
+ fence = fence_get_rcu_safe(&man->move);
+ rcu_read_unlock();
if (fence) {
reservation_object_add_shared_fence(bo->resv, fence);
@@ -1310,9 +1310,9 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
}
spin_unlock(&glob->lru_lock);
- spin_lock(&man->move_lock);
- fence = fence_get(man->move);
- spin_unlock(&man->move_lock);
+ rcu_read_lock();
+ fence = fence_get_rcu_safe(&man->move);
+ rcu_read_unlock();
if (fence) {
ret = fence_wait(fence, false);
@@ -1332,6 +1332,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
{
struct ttm_mem_type_manager *man;
+ struct fence *last_move;
int ret = -EINVAL;
if (mem_type >= TTM_NUM_MEM_TYPES) {
@@ -1345,7 +1346,14 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
mem_type);
return ret;
}
- fence_put(man->move);
+
+ /* The locking here is overkill; but harmless and documentary */
+ spin_lock(&man->move_lock);
+ last_move = rcu_dereference_protected(man->move,
+ spin_is_locked(&man->move_lock));
+ rcu_assign_pointer(man->move, NULL);
+ spin_unlock(&man->move_lock);
+ fence_put(last_move);
man->use_type = false;
man->has_type = false;
@@ -1410,7 +1418,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
man->size = p_size;
INIT_LIST_HEAD(&man->lru);
- man->move = NULL;
+ RCU_INIT_POINTER(man->move, NULL);
return 0;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index f157a9efd220..cd675d503ee4 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -755,6 +755,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
ttm_bo_unref(&ghost_obj);
} else if (from->flags & TTM_MEMTYPE_FLAG_FIXED) {
+ struct fence *last_move;
/**
* BO doesn't have a TTM we need to bind/unbind. Just remember
@@ -762,11 +763,14 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
*/
spin_lock(&from->move_lock);
- if (!from->move || fence_is_later(fence, from->move)) {
- fence_put(from->move);
- from->move = fence_get(fence);
- }
+ last_move = rcu_dereference_protected(from->move,
+ spin_is_locked(&from->move_lock));
+ if (!last_move || fence_is_later(fence, last_move))
+ rcu_assign_pointer(from->move, fence_get(fence));
+ else
+ last_move = NULL;
spin_unlock(&from->move_lock);
+ fence_put(last_move);
ttm_bo_free_old_node(bo);
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 99c6d01d24f2..508d2f428d25 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -305,7 +305,7 @@ struct ttm_mem_type_manager {
/*
* Protected by @move_lock.
*/
- struct fence *move;
+ struct fence __rcu *move;
};
/**
--
2.9.3
More information about the dri-devel
mailing list