Am 29.08.2016 um 18:57 schrieb Chris Wilson:
> 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>

Reviewed-by: 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;
>   };
>   
>   /**


Reply via email to