[PATCH] drm/radeon: disable any GPU activity after unrecovered lockup

j.glisse at gmail.com j.glisse at gmail.com
Tue Jun 26 14:04:01 PDT 2012


From: Jerome Glisse <jglisse at redhat.com>

After unrecovered GPU lockup avoid any GPU activities to avoid
things like kernel segfault and alike to happen in any of the
path that assume hw is working.

cc: stable at vger.kernel.org
Signed-off-by: Jerome Glisse <jglisse at redhat.com>
---
 drivers/gpu/drm/radeon/radeon_device.c |    9 ++++---
 drivers/gpu/drm/radeon/radeon_object.c |    7 ++++++
 drivers/gpu/drm/radeon/radeon_ttm.c    |   41 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ttm/ttm_tt.c           |    1 +
 4 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 066c98b..653f352 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -993,16 +993,19 @@ int radeon_gpu_reset(struct radeon_device *rdev)
 	/* block TTM */
 	resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
 	radeon_suspend(rdev);
+	rdev->accel_working = false;
 
 	r = radeon_asic_reset(rdev);
 	if (!r) {
 		dev_info(rdev->dev, "GPU reset succeed\n");
 		radeon_resume(rdev);
-		radeon_restore_bios_scratch_regs(rdev);
-		drm_helper_resume_force_mode(rdev->ddev);
-		ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
 	}
 
+	/* no matter what restore video mode */
+	radeon_restore_bios_scratch_regs(rdev);
+	drm_helper_resume_force_mode(rdev->ddev);
+	ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
+
 	if (r) {
 		/* bad news, how to tell it to userspace ? */
 		dev_info(rdev->dev, "GPU reset failed\n");
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 830f1a7..27e8e53 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -89,6 +89,13 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
 	rbo->placement.lpfn = 0;
 	rbo->placement.placement = rbo->placements;
 	rbo->placement.busy_placement = rbo->placements;
+	if (!rbo->rdev->accel_working) {
+		/* for new bo to system ram when GPU is not working */
+		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+		rbo->placement.num_placement = c;
+		rbo->placement.num_busy_placement = c;
+		return;
+	}
 	if (domain & RADEON_GEM_DOMAIN_VRAM)
 		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
 					TTM_PL_FLAG_VRAM;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index c94a225..0994d1e 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -215,6 +215,25 @@ static void radeon_move_null(struct ttm_buffer_object *bo,
 	new_mem->mm_node = NULL;
 }
 
+static void radeon_move_noop(struct ttm_buffer_object *bo,
+			     struct ttm_mem_reg *new_mem)
+{
+	struct ttm_bo_device *bdev = bo->bdev;
+	struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
+	struct ttm_mem_reg *old_mem = &bo->mem;
+	struct ttm_mem_reg old_copy = *old_mem;
+
+	*old_mem = *new_mem;
+	new_mem->mm_node = NULL;
+
+	if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm != NULL)) {
+		ttm_tt_destroy(bo->ttm);
+		bo->ttm = NULL;
+	}
+
+	ttm_bo_mem_put(bo, &old_copy);
+}
+
 static int radeon_move_blit(struct ttm_buffer_object *bo,
 			bool evict, int no_wait_reserve, bool no_wait_gpu,
 			struct ttm_mem_reg *new_mem,
@@ -399,6 +418,14 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
 		radeon_move_null(bo, new_mem);
 		return 0;
 	}
+	if (!rdev->accel_working) {
+		/* when accel is not working GPU is in broken state just
+		 * do nothing for any ttm operation to avoid making the
+		 * situation worst than it's
+		 */
+		radeon_move_noop(bo, new_mem);
+		return 0;
+	}
 	if ((old_mem->mem_type == TTM_PL_TT &&
 	     new_mem->mem_type == TTM_PL_SYSTEM) ||
 	    (old_mem->mem_type == TTM_PL_SYSTEM &&
@@ -545,6 +572,13 @@ static int radeon_ttm_backend_bind(struct ttm_tt *ttm,
 		WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n",
 		     ttm->num_pages, bo_mem, ttm);
 	}
+	if (!gtt->rdev->accel_working) {
+		/* when accel is not working GPU is in broken state just
+		 * do nothing for any ttm operation to avoid making the
+		 * situation worst than it's
+		 */
+		return 0;
+	}
 	r = radeon_gart_bind(gtt->rdev, gtt->offset,
 			     ttm->num_pages, ttm->pages, gtt->ttm.dma_address);
 	if (r) {
@@ -559,6 +593,13 @@ static int radeon_ttm_backend_unbind(struct ttm_tt *ttm)
 {
 	struct radeon_ttm_tt *gtt = (void *)ttm;
 
+	if (!gtt->rdev->accel_working) {
+		/* when accel is not working GPU is in broken state just
+		 * do nothing for any ttm operation to avoid making the
+		 * situation worst than it's
+		 */
+		return 0;
+	}
 	radeon_gart_unbind(gtt->rdev, gtt->offset, ttm->num_pages);
 	return 0;
 }
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index fa09daf..f7bdb04 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -181,6 +181,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm)
 	ttm->swap_storage = NULL;
 	ttm->func->destroy(ttm);
 }
+EXPORT_SYMBOL(ttm_tt_destroy);
 
 int ttm_tt_init(struct ttm_tt *ttm, struct ttm_bo_device *bdev,
 		unsigned long size, uint32_t page_flags,
-- 
1.7.10.2



More information about the dri-devel mailing list