drm/ttm: Wait for a BO to become idle before unbinding it from GTT
diff mbox

Message ID 1470390015-7219-1-git-send-email-michel@daenzer.net
State New
Headers show

Commit Message

Michel Dänzer Aug. 5, 2016, 9:40 a.m. UTC
From: Michel Dänzer <michel.daenzer@amd.com>

Fixes hangs under memory pressure, e.g. running the piglit test
tex3d-maxsize concurrently with other tests.

Fixes: 17d33bc9d6ef ("drm/ttm: drop waiting for idle in ttm_bo_evict.")
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |  4 ++--
 drivers/gpu/drm/nouveau/nouveau_bo.c    |  4 ++--
 drivers/gpu/drm/radeon/radeon_ttm.c     |  4 ++--
 drivers/gpu/drm/ttm/ttm_bo.c            |  3 ++-
 drivers/gpu/drm/ttm/ttm_bo_util.c       | 10 +++++++++-
 include/drm/ttm/ttm_bo_driver.h         |  3 ++-
 6 files changed, 19 insertions(+), 9 deletions(-)

Comments

Christian König Aug. 5, 2016, 9:44 a.m. UTC | #1
Am 05.08.2016 um 11:40 schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> Fixes hangs under memory pressure, e.g. running the piglit test
> tex3d-maxsize concurrently with other tests.
>
> Fixes: 17d33bc9d6ef ("drm/ttm: drop waiting for idle in ttm_bo_evict.")
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>

Ah, yes of course. Good catch, patch is Reviewed-by: Christian König 
<christian.koenig@amd.com>.

Regards,
Christian.

> ---
>   drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c |  4 ++--
>   drivers/gpu/drm/nouveau/nouveau_bo.c    |  4 ++--
>   drivers/gpu/drm/radeon/radeon_ttm.c     |  4 ++--
>   drivers/gpu/drm/ttm/ttm_bo.c            |  3 ++-
>   drivers/gpu/drm/ttm/ttm_bo_util.c       | 10 +++++++++-
>   include/drm/ttm/ttm_bo_driver.h         |  3 ++-
>   6 files changed, 19 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> index b7742e6..9b61c8b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
> @@ -335,7 +335,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
>   	if (unlikely(r)) {
>   		goto out_cleanup;
>   	}
> -	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
> +	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
>   out_cleanup:
>   	ttm_bo_mem_put(bo, &tmp_mem);
>   	return r;
> @@ -368,7 +368,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
>   	if (unlikely(r)) {
>   		return r;
>   	}
> -	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
> +	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
>   	if (unlikely(r)) {
>   		goto out_cleanup;
>   	}
> diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
> index 528bdef..6190035 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_bo.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
> @@ -1151,7 +1151,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
>   	if (ret)
>   		goto out;
>   
> -	ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
> +	ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, new_mem);
>   out:
>   	ttm_bo_mem_put(bo, &tmp_mem);
>   	return ret;
> @@ -1179,7 +1179,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
>   	if (ret)
>   		return ret;
>   
> -	ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
> +	ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, &tmp_mem);
>   	if (ret)
>   		goto out;
>   
> diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
> index 1cb7266..557ef0c 100644
> --- a/drivers/gpu/drm/radeon/radeon_ttm.c
> +++ b/drivers/gpu/drm/radeon/radeon_ttm.c
> @@ -346,7 +346,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
>   	if (unlikely(r)) {
>   		goto out_cleanup;
>   	}
> -	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
> +	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
>   out_cleanup:
>   	ttm_bo_mem_put(bo, &tmp_mem);
>   	return r;
> @@ -379,7 +379,7 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
>   	if (unlikely(r)) {
>   		return r;
>   	}
> -	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
> +	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
>   	if (unlikely(r)) {
>   		goto out_cleanup;
>   	}
> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
> index 3452748..f078038 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> @@ -355,7 +355,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
>   
>   	if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
>   	    !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
> -		ret = ttm_bo_move_ttm(bo, evict, no_wait_gpu, mem);
> +		ret = ttm_bo_move_ttm(bo, evict, interruptible, no_wait_gpu,
> +				      mem);
>   	else if (bdev->driver->move)
>   		ret = bdev->driver->move(bo, evict, interruptible,
>   					 no_wait_gpu, mem);
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
> index 2df602a..f157a9e 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> @@ -45,7 +45,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
>   }
>   
>   int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
> -		    bool evict,
> +		    bool evict, bool interruptible,
>   		    bool no_wait_gpu, struct ttm_mem_reg *new_mem)
>   {
>   	struct ttm_tt *ttm = bo->ttm;
> @@ -53,6 +53,14 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
>   	int ret;
>   
>   	if (old_mem->mem_type != TTM_PL_SYSTEM) {
> +		ret = ttm_bo_wait(bo, interruptible, no_wait_gpu);
> +
> +		if (unlikely(ret != 0)) {
> +			if (ret != -ERESTARTSYS)
> +				pr_err("Failed to expire sync object before unbinding TTM\n");
> +			return ret;
> +		}
> +
>   		ttm_tt_unbind(ttm);
>   		ttm_bo_free_old_node(bo);
>   		ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
> diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
> index 4348d6d..99c6d01 100644
> --- a/include/drm/ttm/ttm_bo_driver.h
> +++ b/include/drm/ttm/ttm_bo_driver.h
> @@ -962,6 +962,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev,
>    *
>    * @bo: A pointer to a struct ttm_buffer_object.
>    * @evict: 1: This is an eviction. Don't try to pipeline.
> + * @interruptible: Sleep interruptible if waiting.
>    * @no_wait_gpu: Return immediately if the GPU is busy.
>    * @new_mem: struct ttm_mem_reg indicating where to move.
>    *
> @@ -976,7 +977,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev,
>    */
>   
>   extern int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
> -			   bool evict, bool no_wait_gpu,
> +			   bool evict, bool interruptible, bool no_wait_gpu,
>   			   struct ttm_mem_reg *new_mem);
>   
>   /**

Patch
diff mbox

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index b7742e6..9b61c8b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -335,7 +335,7 @@  static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
 	if (unlikely(r)) {
 		goto out_cleanup;
 	}
-	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
 out_cleanup:
 	ttm_bo_mem_put(bo, &tmp_mem);
 	return r;
@@ -368,7 +368,7 @@  static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
 	if (unlikely(r)) {
 		return r;
 	}
-	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
 	if (unlikely(r)) {
 		goto out_cleanup;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 528bdef..6190035 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1151,7 +1151,7 @@  nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 	if (ret)
 		goto out;
 
-	ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+	ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, new_mem);
 out:
 	ttm_bo_mem_put(bo, &tmp_mem);
 	return ret;
@@ -1179,7 +1179,7 @@  nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
 	if (ret)
 		return ret;
 
-	ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+	ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, &tmp_mem);
 	if (ret)
 		goto out;
 
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 1cb7266..557ef0c 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -346,7 +346,7 @@  static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
 	if (unlikely(r)) {
 		goto out_cleanup;
 	}
-	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
 out_cleanup:
 	ttm_bo_mem_put(bo, &tmp_mem);
 	return r;
@@ -379,7 +379,7 @@  static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
 	if (unlikely(r)) {
 		return r;
 	}
-	r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+	r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
 	if (unlikely(r)) {
 		goto out_cleanup;
 	}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 3452748..f078038 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -355,7 +355,8 @@  static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
 
 	if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
 	    !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
-		ret = ttm_bo_move_ttm(bo, evict, no_wait_gpu, mem);
+		ret = ttm_bo_move_ttm(bo, evict, interruptible, no_wait_gpu,
+				      mem);
 	else if (bdev->driver->move)
 		ret = bdev->driver->move(bo, evict, interruptible,
 					 no_wait_gpu, mem);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 2df602a..f157a9e 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -45,7 +45,7 @@  void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
 }
 
 int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
-		    bool evict,
+		    bool evict, bool interruptible,
 		    bool no_wait_gpu, struct ttm_mem_reg *new_mem)
 {
 	struct ttm_tt *ttm = bo->ttm;
@@ -53,6 +53,14 @@  int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
 	int ret;
 
 	if (old_mem->mem_type != TTM_PL_SYSTEM) {
+		ret = ttm_bo_wait(bo, interruptible, no_wait_gpu);
+
+		if (unlikely(ret != 0)) {
+			if (ret != -ERESTARTSYS)
+				pr_err("Failed to expire sync object before unbinding TTM\n");
+			return ret;
+		}
+
 		ttm_tt_unbind(ttm);
 		ttm_bo_free_old_node(bo);
 		ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 4348d6d..99c6d01 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -962,6 +962,7 @@  void ttm_mem_io_free(struct ttm_bo_device *bdev,
  *
  * @bo: A pointer to a struct ttm_buffer_object.
  * @evict: 1: This is an eviction. Don't try to pipeline.
+ * @interruptible: Sleep interruptible if waiting.
  * @no_wait_gpu: Return immediately if the GPU is busy.
  * @new_mem: struct ttm_mem_reg indicating where to move.
  *
@@ -976,7 +977,7 @@  void ttm_mem_io_free(struct ttm_bo_device *bdev,
  */
 
 extern int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
-			   bool evict, bool no_wait_gpu,
+			   bool evict, bool interruptible, bool no_wait_gpu,
 			   struct ttm_mem_reg *new_mem);
 
 /**